格式化带有多个百分号的字符串
Format string with multiple percent signs
我知道 %%
用于转义字符串中的实际 %
符号,因此 %%%ds
将在以下格式字符串中以 %10s
结束,但我不知道为什么我需要在这个字符串中使用 %%5s
?
毕竟,只有两个附加参数(BUFFSIZE / 10)。
#define BUFFSIZE 100
char buf[100]={0}
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE / 10, BUFFSIZE / 10);
在运行上面的代码之后,buf将包含字符串,
%10s %10s
目的是获取一个格式字符串,以便在另一个需要像 sscanf()
.
这样的格式字符串的函数中使用它
使用您的代码,您将获得:%5s %10s %10s
写入您的 buf
、see online,这意味着它将接受三个具有长度标识符的字符串。
%%5s --> %5s
%%%ds with 10 --> %10s (read it that way: {%%}{%d}{s})
缓冲区 %5s %10s %10s
现在可以在 sscanf()
调用中使用,如图 here。
但是有一个最佳实践可以防止由 sscanf()
引起的缓冲区溢出,Kernighan 和 Pike 在他们的书中也有描述 The Practice of Programming, see here on SO.
您可能无法使用 %*s
的原因可能是,请参阅 here on SO:
For printf
, the * allows you to specify minimum field width through an extra parameter, i.e. printf("%*d", 4, 100);
specifies a field width of 4.
For scanf
, the * indicates that the field is to be read but ignored, so that i.e. scanf("%*d %d", &i)
for the input "12 34" will ignore 12 and read 34 into the integer i.
%
本身就是一个有效的转换说明符。如 C11
章节 §7.21.6.1/P2 中所述,规定的语法是 (emphasis mine)
Each conversion specification is introduced by the character %
. After the %
, the following
appear in sequence:
Zero or more flags [...]
An optional minimum field width.
An optional precision [...]
An optional length modifier [...]
A conversion specifier character that specifies the type of conversion to be applied.
然后,从 P8 开始,对于转换说明符
The conversion specifiers and their meanings are:
......
%
A %
character is written. No argument is converted. The complete
conversion specification shall be %%
.
因此,基于贪婪的方法,编译器会将语法分组为
.... %%%ds, BUFFSIZE / 10 ....
作为
{%%}{%d}{s}
^^--------------------------Replaced as %
^^----------------------Actual conversion specification happens, argument is used
^^------------------just part of final output
最终产生
%Xs //where X is the value of (BUFFSIZE / 10)
这是一个有效的格式字符串(%
,最小字段宽度,转换说明符,全部按顺序),同样,稍后使用。
OP 正在根据参数大小计算格式字符串。给定参数,字符串将包含 %5s %10s %10s
,它可以与 printf
或 scanf
:
一起使用
printf("%5s %10s %10s", "A", "B", "C");
输出:
A B C
char a[6], b[11], c[11];
scanf("%5s %10s %10s", a, b, c);
会将 3 个字符串读入 a
、b
、c
,但会限制为每个字符串读取的字符数以防止缓冲区溢出。
但是请注意,对于 printf
的情况,没有必要计算发布的字符串,因为您可以使用:
printf("%5s %*s %*s", "A", BUFFSIZE / 10, "B", BUFFSIZE / 10, "C");
不幸的是,scanf()
将不同的语义附加到 *
格式修饰符,并且无法指定要使用参数存储的最大字符数,只能使用格式字符串中的数字,因此需要一个单独的格式化步骤。
我知道 %%
用于转义字符串中的实际 %
符号,因此 %%%ds
将在以下格式字符串中以 %10s
结束,但我不知道为什么我需要在这个字符串中使用 %%5s
?
毕竟,只有两个附加参数(BUFFSIZE / 10)。
#define BUFFSIZE 100
char buf[100]={0}
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE / 10, BUFFSIZE / 10);
在运行上面的代码之后,buf将包含字符串,
%10s %10s
目的是获取一个格式字符串,以便在另一个需要像 sscanf()
.
使用您的代码,您将获得:%5s %10s %10s
写入您的 buf
、see online,这意味着它将接受三个具有长度标识符的字符串。
%%5s --> %5s
%%%ds with 10 --> %10s (read it that way: {%%}{%d}{s})
缓冲区 %5s %10s %10s
现在可以在 sscanf()
调用中使用,如图 here。
但是有一个最佳实践可以防止由 sscanf()
引起的缓冲区溢出,Kernighan 和 Pike 在他们的书中也有描述 The Practice of Programming, see here on SO.
您可能无法使用 %*s
的原因可能是,请参阅 here on SO:
For
printf
, the * allows you to specify minimum field width through an extra parameter, i.e.printf("%*d", 4, 100);
specifies a field width of 4.For
scanf
, the * indicates that the field is to be read but ignored, so that i.e.scanf("%*d %d", &i)
for the input "12 34" will ignore 12 and read 34 into the integer i.
%
本身就是一个有效的转换说明符。如 C11
章节 §7.21.6.1/P2 中所述,规定的语法是 (emphasis mine)
Each conversion specification is introduced by the character
%
. After the%
, the following appear in sequence:
Zero or more flags [...]
An optional minimum field width.
An optional precision [...]
An optional length modifier [...]
A conversion specifier character that specifies the type of conversion to be applied.
然后,从 P8 开始,对于转换说明符
The conversion specifiers and their meanings are:
......
%
A
%
character is written. No argument is converted. The complete conversion specification shall be%%
.
因此,基于贪婪的方法,编译器会将语法分组为
.... %%%ds, BUFFSIZE / 10 ....
作为
{%%}{%d}{s}
^^--------------------------Replaced as %
^^----------------------Actual conversion specification happens, argument is used
^^------------------just part of final output
最终产生
%Xs //where X is the value of (BUFFSIZE / 10)
这是一个有效的格式字符串(%
,最小字段宽度,转换说明符,全部按顺序),同样,稍后使用。
OP 正在根据参数大小计算格式字符串。给定参数,字符串将包含 %5s %10s %10s
,它可以与 printf
或 scanf
:
printf("%5s %10s %10s", "A", "B", "C");
输出:
A B C
char a[6], b[11], c[11];
scanf("%5s %10s %10s", a, b, c);
会将 3 个字符串读入 a
、b
、c
,但会限制为每个字符串读取的字符数以防止缓冲区溢出。
但是请注意,对于 printf
的情况,没有必要计算发布的字符串,因为您可以使用:
printf("%5s %*s %*s", "A", BUFFSIZE / 10, "B", BUFFSIZE / 10, "C");
不幸的是,scanf()
将不同的语义附加到 *
格式修饰符,并且无法指定要使用参数存储的最大字符数,只能使用格式字符串中的数字,因此需要一个单独的格式化步骤。