2013-07-16 170 views
0

任何人都可以解释这些输出背后的逻辑吗?我想这里使用*作为抑制字符,但我无法弄清楚输出。在printf语句中使用*

main() 
{ 
char *s="hello world"; 
int i=7; 
printf("%.*%s",s); 
} 

输出:%s的

如果更换printf语句为printf("%,*%s",s)那么你的输出将是,*你好世界???

+3

你的问题说'scanf',但你的代码说'printf'。这是什么? –

+0

对不起,我错误地写了scanf,它会被printf.I编辑它。 –

回答

6

printf格式字符串"%.*%s"无效。 *字符不被视为转换抑制说明符,而是作为指定精度的.字符的参数。

与类似比较:

printf("%.*s", 3, str); 

其中*采取下一个参数(3)的精度域(其具有用于串的特定的含义),然后将s需要的字符串。由于3是一个常数,这相当于硬编码格式字符串:

printf("%.3s", str); 

所以,你有什么在这里是为%.*它看起来像一个可变精度场转换的开始。它将消耗s参数并将其视为int,这是未定义的行为。

即使下一个参数实际上是一个int,那么接下来会发生的情况是,%字符跟在*变量精度之后并不是有效的转换说明符。或者,它是一个有效的转换说明符,作为%%转换的一部分。但编号为%%%序列不支持两个字符之间的可选材料。 ISO 9899:1999(%说明符)指出“完整的转换规范应为%%”。

它也表示“如果转换规范无效,行为未定义。”一个%%规范,其中像宽度或精度字段之间的材料,是无效的,因为它违反了明确规定的要求,即“完整的转换规范应为%%”。

+0

好吧,但我不认为格式字符串像''%。*%s“'是**无效的**,它不是人们通常想要的,但它完全兼容**与ANSI C标准。对不起,我无法找出现在指定的部分。 – starrify

+0

我的ISO9899:1999版本说“如果转换规范无效,行为是未定义的”。摸索格式字符串的后果是严重的。 :) – Kaz

+0

是的,你是对的,请检查我的更新我的答案。 :D – starrify

1

这里您格式化字符串被解释为两个部分"%.*%""s",其中前者是规定的最大宽度的“逃脱”百分号(这是你*在这里所做的)的指针s的价值。尝试先删除第二个百分号。

对不起,我想我会为你先试试这个,但它是目前不方便对我..

编辑:

是,要得到你想要的,你应该这样写的:

// here width is a customized value you pass to specify the maximum width of string 
printf("%.*s", width, s); 

// and this would give "hello worl" as its output. notice the missing "d" 
printf("%.*s", 10, s); 

再次编辑:

PLZ检查the reference manual of printf

宽度:
字段的宽度在这里指定用十进制值。如果值不足以填充宽度,则字段的其余部分用空格填充(除非指定了0标志)。如果该值溢出字段的宽度,则该字段将展开以适合该值。如果使用*代替宽度指定符,则下一个参数(必须是int类型)指定该字段的宽度。注意:当使用宽度和/或精度说明符时,首先输入width参数,然后输入precision参数,然后输入要转换的值。

再次编辑:

@Kaz是正确的有关标准。见ISO-IEC-9899_1990(版本2第137页):

%匹配单个%:不进行转换或分配。完整转换 规范应为%%

因此,在两个百分号之间插入任何其他转换说明符都会导致未定义的行为。

1

为了回答您的具体问题,是病态,形成你的第一个printf()声明,因为它没有提供int参数*改性剂,以及使用精确到%转换说明是不确定的。根据你的情况,似乎你的C实现是忽略了精度,使打印语句相当于:printf("%%s",s);,这将导致输出:

%s 

%%转换为输出一个%)。

对于您的第二个printf()声明,由于您提供了无效的转换说明符,,所以它又是格式不正确。使用此说明符的行为会导致未定义的行为。您的系统似乎输出错误说明符,然后输出*,然后处理输出字符串的%s

,*hello world 

printf(),所述*改性剂到转换指定是供给从参数的字段宽度或精度(或两者)的printf()呼叫(而不是硬编码号码直入的方式格式字符串本身)。所以:

char *s="hello world"; 
int i=7; 
printf("%.*s\n", i, s); 

将打印输出:

hello w 

在这种情况下,*是精度,因为它沿用了小数点。对于字符串,这意味着将要打印的字符串中的最大字符数。

+0

是的,终于明白了。谢谢 –