请看一下这个代码片段:
char line1[10], line2[10];
int rtn;
rtn = scanf("%9[a]%9[^\n]", line1, line2);
printf("line1 = %s|\nline2 = %s|\n", line1, line2);
printf("rtn = %d\n", rtn);
输出:
$ gcc line.c -o line
$ ./line
abook
line1 = a|
line2 = book|
rtn = 2
$./line
book
line1 = |
line2 = �Js�|
rtn = 0
$
对于输入abook,从%9[a]处失败并存储先前解析的+处。
然后解析剩余的行并存储刚才解析的+ at 。
请注意这里的2点: bbooka\0line1%9[^\n]book\0line2
- 在存储解析后的输入时,由于是字符串的转换说明符
\0,因此会在其末尾附加。%[] %9[a]失败时,b没有scanf退出。它只是继续扫描进一步的输入。
现在对于 input book,应该从%9[a]失败并且应该存储在因为这里没有被解析。然后应该解析剩余的行并且应该存储刚刚解析的+ at 。 bbook\0line1%9[^\n]book\0line2
现在,让我们看看到底发生了什么:
这里的返回值为 0,这意味着scanf没有为任何变量赋值。scanf简单地退出而不分配任何值。所以垃圾数据在line2。在line1这种垃圾数据的情况下,恰好是一个NULL字符。
但这很奇怪!不是吗?
我的意思是如果在输入的第一个字符处失败则scanf退出。%[...](即使scanf语句中存在额外的转换说明符。)
但是如果在%[...]除第一个字符之外的任何其他字符处同样失败,则scanf只需继续扫描进一步的输入。(当然,如果有额外的转换说明符。)它不会退出。
那么为什么会出现这种不一致呢?为什么不让scanf语句继续扫描输入(如果当然有额外的转换说明符)即使%[...]在输入的第一个字符处失败?就像在其他情况下发生的一样。
这种不一致的背后有什么特殊原因吗?
$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3