格式字符串与多个百分号

问题描述:

我知道%%用来逃避字符串中的实际%迹象,所以%%%ds最终会在以下格式字符串%10s,但我不知道为什么我在这个字符串需要%%5s格式字符串与多个百分号

毕竟,只有两个附加参数(BUFFSIZE/10)。

#define BUFFSIZE 100 
char buf[100]={0} 
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE/10, BUFFSIZE/10); 

运行上面的代码后,BUF将包含字符串,

%10s %10s 
+5

我在'buf'中获得'%5s%10s%10s',在这里演示http://ideone.com/c8MhN6。 _you_期望什么? –

+2

这意味着某人要么过于聪明,要么不知道['%* s'](https://*.com/questions/7105890/set-variable-text-column-width-in-printf)。 –

+1

@ n.m。或者,不怕维护者(_Ref:暴力精神病患者) –

的目的是为了获得一个格式字符串中,需要一个格式字符串像sscanf()另一个函数来使用它。

使用您的代码,您将得到:%5s %10s %10s写入您的bufsee 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中也描述了缓冲区溢出,请参见here on SO


为什么你也许不能使用%*s可能是这个原因,看here on SO

printf,则*允许您通过一个额外的参数指定最小字段宽度,即printf("%*d", 4, 100);指定字段宽度为4.

对于scanf,*表示该字段将被读取但被忽略,因此,即输入“12 34”的scanf("%*d %d", &i)将忽略12并将其读入整数i。

%本身是一个有效的转换说明符。在规定的语法,如在C11,章§7.21.6.1/ P2,(重点煤矿

每种转换规范由字符%引入提及。 %后,以下 出现在序列:

  • 零个或更多个标志[...]

  • 可选最小字段宽度。

  • 可选的精度[...]

  • 可选长度修改[...]

  • 转换说明符字符,指定要应用的转换类型。

然后,P8,用于转换说明

转换标识符和它们的含义如下:

......

%

A %字符被写入。没有参数被转换。完整的 转换规范应为%%

因此,基于贪婪方法,编译器将组像

.... %%%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) 

这是一个有效格式字符串(%,最小字段宽度,转换说明符,全部按顺序),以后再使用。

+0

你解释了一切,我的错误 –

+0

@VishwajeetVishu Nevermind,没关系。同时我也在更新答案。 :) –

OP从参数大小计算格式字符串。给定的参数,该字符串将包含%5s %10s %10s,其可与任一printfscanf使用:

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串入abc但限制了数为每个字符串读取字符以防止缓冲区溢出。

不过请注意,对于printf情况下,没有必要计算字符串作为贴了,因为你也可以使用:

printf("%5s %*s %*s", "A", BUFFSIZE/10, "B", BUFFSIZE/10, "C"); 

不幸的是,scanf()高度不同的语义为*格式修改,这是无法指定要使用参数存储的最大字符数,只能使用格式字符串中的数字,因此需要单独的格式化步骤。