PrintF字符串,可变长度项。

55
#define SIZE 9
int number=5;
char letters[SIZE]; /* this wont be null-terminated */
... 

char fmt_string[20];
sprintf(fmt_string, "%%d %%%ds", SIZE);
/* fmt_string = "%d %9d"... or it should be */

printf(fmt_string, number, letters);

有更好的做法吗?


你似乎正在构建一个格式化字符串。但是你应该将sprintf返回的字符串赋值给fmt_string,而且fmt_string不应该在参数列表中。 - pavium
你说 letters 不会以 NULL 结尾,有什么特别的原因吗? - Andrew Keeton
1
@AndrewKeeton 这是一个涉及大型数据集的搜索问题,我无法承受保存空字符所需的空间。 - William Entriken
请注意:这是https://dev59.com/YHE95IYBdhLWcg3wmvGh的重复内容。 - pevik
2个回答

133

不需要构造特殊的格式字符串。如果在格式标记中使用.*作为精度,并将其作为参数(在值之前)进行指定,printf即可允许您指定该精度。

例如:

printf ("%d %.*s", number, SIZE, letters);
注意:宽度(即最小字段宽度)和精度(即要打印的最大字符数)是有区别的。 %*s指定宽度,%.s指定精度。(你也可以使用%*.*,但这需要两个参数,一个用于宽度,一个用于精度。)
另请参阅printf手册页(Linux下的man 3 printf),特别是有关字段宽度和精度的部分:

可以写"*"或"*m$"(对于某个十进制整数m)代替十进制数字字符串,以指定下一个参数或第m个参数中给出精度,这些参数必须为int类型。


把它们搞混了... scanf 是那个没有这个选项的。 - William Entriken
6
它还支持两个长度参数,格式为"%*.*s",分别表示最小长度和最大长度,用于控制字母的输出。 - ott--
注意:"*m$" 不是标准的 C 语言。 - chux - Reinstate Monica
2
有没有办法让“%.*s”格式接受size_t而不是int - Jimmay

6

一个比较不为人知的函数是asprintf。第一个参数是**char。该函数将malloc字符串所需的空间,因此您无需进行簿记。完成后,请记得free字符串。

char *fmt_string;

asprintf(&fmt_string, "%%d %%%ds", SIZE);
printf(fmt_string, number, letters);
free(fmt_string);

这是一个使用示例。

3
尽管asprintf是一个很有趣的函数,但需要注意它是GNU扩展。另外,我不确定这如何回答问题。 - Trent
2
@Trent,它最初确实是GNU扩展,但与此同时,OpenBSD、FreeBSD和NetBSD已经实现了它。甚至Mac OS X现在也有它了。 - Cristian Ciupitu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接