读取数字和换行符时出现奇怪的scanf行为

时间:2014-02-17 12:12:50

标签: c scanf gets

我刚刚意识到scanf的这个'bug',现在已经过了8年了。

scanf代码下方将跳过第二行输入的前导空白字符。

int x;
char in[100];

scanf("%d\n",&x);
gets(in);

输入:

1
     s

x将包含1,但in只会"s"而不会" s"

这是标准C还是gcc行为?

3 个答案:

答案 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