我刚刚意识到scanf的这个'bug',现在已经过了8年了。
scanf代码下方将跳过第二行输入的前导空白字符。
int x;
char in[100];
scanf("%d\n",&x);
gets(in);
输入:
1
s
x
将包含1
,但in
只会"s"
而不会" s"
这是标准C还是gcc行为?
答案 0 :(得分:2)
scanf
格式字符串中的空白字符将导致scanf
使用任何(和所有)空格,直到出现非空白字符。
这似乎是标准scanf
行为,并不仅限于gcc。
答案 1 :(得分:1)
这不是scanf
中的错误,scanf的说明,
一系列空格字符(空格,制表符,换行符等;请参阅
isspace(3)
)。该指令匹配任意数量的空白区域, 包括无,在输入中。
这意味着任何带有指令%d\n
的空白字符都会读取一个数字,然后在输入中使用一系列空白字符,直到您键入非空白字符为止。这就是你如何能够只看到"s"
之前没有空格。
答案 2 :(得分:0)
'\n'
(对于格式字符串中的任何空格字符都是如此)
scanf("%d\n", &x);
匹配输入中的任意数量的空白字符(isspace
函数返回1的字符,即true,如换行符,空格,制表符等)而不仅仅是换行符'\n'
。这意味着scanf
将读取输入中的所有空白字符并将其丢弃,直到遇到非空白字符。这解释了您观察到的行为。
这是scanf
功能的标准定义的一部分,而不是gcc
功能。此外,gets
功能已弃用且不安全。它不会检查缓冲区溢出,并可能导致错误甚至程序崩溃。实际上,gcc
会在我的计算机上发出gets
警告。建议使用fgets
。
要做你想做的事,你可以做到以下几点:
int x;
char in[100];
scanf("%d", &x);
scanf
成功返回后,输入流可以包含由换行符终止的任何字符序列,具体取决于用户提供的输入。在从标准输入读取字符串之前去掉那些无关紧要的字符。
char ch;
while((ch = getchar()) != '\n' || ch != EOF); // null statement
fgets(in, 100, stdin);
上面的fgets
调用意味着它将最多读取100-1 = 99
(它为终止空字节保存一个字符空间,它将在退出之前添加到正在读取的缓冲区中)来自流中的字符由stdin
指向并将它们存储在in
指向的缓冲区中。 fgets
如果遇到EOF
,'\n'
或已经读取了100-1个字符,则会退出 - 这三个条件中的任何一个首先出现。如果它读取换行符,它会将其存储到缓冲区中。
在这种情况下,用户是否输入100个字符或更多字符,然后输入缓冲区中会出现多余的字符,这可能会导致scanf
,{{1}后面的字符或字符串输入操作陷入混乱}},fgets
等来电。您可以检查字符串getchar
的长度。
in