任何人都可以解释这些输出背后的逻辑吗?我想这里使用*
作为抑制字符,但我无法弄清楚输出。在printf语句中使用*
main()
{
char *s="hello world";
int i=7;
printf("%.*%s",s);
}
输出:%s的
如果更换printf语句为printf("%,*%s",s)
那么你的输出将是,*你好世界???
任何人都可以解释这些输出背后的逻辑吗?我想这里使用*
作为抑制字符,但我无法弄清楚输出。在printf语句中使用*
main()
{
char *s="hello world";
int i=7;
printf("%.*%s",s);
}
输出:%s的
如果更换printf语句为printf("%,*%s",s)
那么你的输出将是,*你好世界???
printf格式字符串"%.*%s"
无效。 *
字符不被视为转换抑制说明符,而是作为指定精度的.
字符的参数。
与类似比较:
printf("%.*s", 3, str);
其中*
采取下一个参数(3)的精度域(其具有用于串的特定的含义),然后将s
需要的字符串。由于3
是一个常数,这相当于硬编码格式字符串:
printf("%.3s", str);
所以,你有什么在这里是为%.*
它看起来像一个可变精度场转换的开始。它将消耗s
参数并将其视为int
,这是未定义的行为。
即使下一个参数实际上是一个int,那么接下来会发生的情况是,%
字符跟在*
变量精度之后并不是有效的转换说明符。或者,它是一个有效的转换说明符,作为%%
转换的一部分。但编号为%
的%%
序列不支持两个字符之间的可选材料。 ISO 9899:1999(%
说明符)指出“完整的转换规范应为%%
”。
它也表示“如果转换规范无效,行为未定义。”一个%%
规范,其中像宽度或精度字段之间的材料,是无效的,因为它违反了明确规定的要求,即“完整的转换规范应为%%
”。
这里您格式化字符串被解释为两个部分"%.*%"
和"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页):
%匹配单个%:不进行转换或分配。完整转换 规范应为%%
因此,在两个百分号之间插入任何其他转换说明符都会导致未定义的行为。
为了回答您的具体问题,是病态,形成你的第一个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
在这种情况下,*
是精度,因为它沿用了小数点。对于字符串,这意味着将要打印的字符串中的最大字符数。
是的,终于明白了。谢谢 –
你的问题说'scanf',但你的代码说'printf'。这是什么? –
对不起,我错误地写了scanf,它会被printf.I编辑它。 –