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

我只是在用C做了8年后才意识到scanf的’bug’。

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

int x; char in[100]; scanf("%d\n",&x); gets(in); 

输入:

 1 s 

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

这个标准C还是gcc行为?

scanf格式字符串中的空格字符将导致scanf消耗任何(和所有)空白区域,直到出现非空白字符。

这似乎是标准的scanf行为,并不仅限于gcc。

它不是scanf的Bug, scanf的手册说,

一系列空格字符(空格,制表符,换行符等;请参阅isspace(3) )。 该指令匹配输入中的任何数量的空白区域,包括无空格。

这意味着任何带有指令%d\n空白字符将读取一个数字,然后在输入中使用一系列空白字符,并且只有在您键入非空白字符时才会返回。 那你怎么能只看到没有空格的"s"

'\n' (对于格式字符串中的任何空格字符都是如此)

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

匹配输入中的任意数量的空白字符( isspace函数返回1的字符,即true,如换行符,空格,制表符等),而不仅仅是换行符'\n' 。 这意味着scanf将读取输入中的所有空白字符并将其丢弃,直到遇到非空白字符。 这解释了您观察到的行为。

这是scanf函数的标准定义的一部分,而不是gccfunction。 此外, getsfunction已被弃用 且不安全 。 它不会检查缓冲区溢出,并可能导致错误甚至程序崩溃。 事实上, gcc发出警告,反对在我的机器上使用gets 。 建议使用fgets

要做你想做的事,你可以做以下事情:

 int x; char in[100]; scanf("%d", &x); 

scanf成功返回后,输入流可以包含由换行符终止的任何字符序列,具体取决于用户给出的输入。 在从stdin读取字符串之前去除那些无关的字符。

 char ch; while((ch = getchar()) != '\n' || ch != EOF); // null statement fgets(in, 100, stdin); 

上面的fgets调用意味着它将最多读取100-1 = 99 (它为终止空字节保存一个字符空间,它将在退出之前添加到正在读取的缓冲区中)来自stdin指向的流中的字符并存储它们在缓冲区中指向的。 如果遇到EOF'\n'或者它已经读取了100-1个字符,则fgets将退出 – 这三个条件中的任何一个首先出现。 如果它读取换行符,它会将其存储到缓冲区中。

在这种情况下,用户是否输入100个字符或更多字符,那么无关的字符将位于输入缓冲区中,这可能会影响scanffgetsgetchar等调用后续字符或字符串的输入操作。 您可以检查此字符串的长度。

 if(strlen(in) > 99) { // extraneous chars lying around in the input buffer // read and discard them char ch; while((ch = getchar()) != '\n' || ch != EOF); // null statement }