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

读取数字和换行符时奇怪的scanf行为,c,scanf,gets,C,Scanf,Gets,在使用C语言8年后,我现在才意识到scanf的这个“缺陷” 下面的scanf代码将跳过第二行输入的前导空格字符 int x; char in[100]; scanf("%d\n",&x); gets(in); 输入: 1 s x将包含1,但中的将只是“s”而不是“s” 这是标准的C还是gcc行为?的手册上说,这不是scanf中的一个Bug 一系列空白字符(空格、制表符、换行符等;请参阅 isspace(3))。此指令匹配任意数量的空白, 在输入中包括无 这意味着指令为%d

在使用C语言8年后,我现在才意识到scanf的这个“缺陷”

下面的scanf代码将跳过第二行输入的前导空格字符

int x;
char in[100];

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

1
     s
x
将包含
1
,但
中的
将只是
“s”
而不是
“s”


这是标准的C还是gcc行为?

的手册上说,这不是scanf中的一个Bug

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

这意味着指令为
%d\n
的任何空白字符都将读取一个数字,然后在输入中使用一系列空白字符,并且仅在键入非空白字符之前返回。这样您就可以只看到
“s”
,前面没有空格

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

这是
scanf
功能标准定义的一部分,而不是
gcc
功能。另外,
获取
函数已弃用不安全。它不会检查缓冲区溢出,并可能导致错误,甚至程序崩溃。事实上,
gcc
发出警告,禁止在我的机器上使用
get
。建议改用
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
调用意味着它将从
stdin
指向的流中读取最多
100-1=99
(它为终止空字节节省一个字符空间,该字节在退出之前添加到正在读取的缓冲区中)的字符,并将它们存储在
中的
指向的缓冲区中<如果遇到
EOF
'\n'
或已读取100-1个字符,则代码>fgets
将退出-以先出现的三种情况中的任何一种为准。如果它读取新行,它将把它存储到缓冲区中

如果用户在这种情况下输入100个或更多字符,那么多余的字符将被放置在输入缓冲区中,这可能会通过
scanf
fgets
getchar
等调用打乱字符或字符串的后续输入操作。您可以在
中检查字符串的长度

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
} 

scanf
格式字符串中的空白字符将导致
scanf
占用任何(和所有)空白,直到出现非空白字符


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

阅读btw scanf超过8年:)您没有阅读scanf
手册,但换行符仍在输入缓冲区中。
-不,由于
\n
格式字符串
gets()当您再次延迟读取字符串时,将立即读取此换行符给您一个空格,这不是因为GET只读取
s
,这就是输出仅为
“s”
的原因。我想与大家分享一个关于@GrijeshChauhan的教程,我急于回答并犯了一个错误。感谢你的链接。答案已编辑。@SunEric那么这意味着scanf(“%d\t”、&x)和scanf(“%d”、&x)以及scanf(“%d\n”、&x)的行为完全相同?我认为它将分别消耗到字符“\t”或“\n”为止。
跳过任何(和所有)空白
我认为最好说类似的内容将消耗所有空白,直到出现非空白字符为止。因为scanf不会跳过,而是从输入缓冲区中删除。+,因为下面两个答案都是错误的。。您可能还希望包括scanf仅在读取
s
(非空白)时返回调用位置,但不消耗[]
数组中
get()
读取的输入缓冲区中的remove
s
。所以只需输出
“s”
@ajay操作正在执行
scanf(“%d\n”,&x)
scanf(“%d”和&x)。格式字符串中的
\n
占用了数字后面的空白。@Klaslindbkäck感谢Klas让我在链接和常见问题解答
中弄糊涂了,换行符是由gets调用读取的
否\n不是由getsAjay读取的请不要介意,但仍然需要更正
换行符在输入后留在输入缓冲区中输入一个int并点击
,因为Scanf会消耗所有的空格并从stdin中删除(但不存储在任何地方)。@GrijeshChauhan
'\n'
gets
读取,但不会保存到传递给它的缓冲区中并被丢弃。
gets()
s
之后读取一个
\n
,并丢弃它。阅读,但问题是关于
\n
“s”
之前的空格,而不是
s
之后遇到的空格
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
}