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