读取数字和换行符时奇怪的scanf行为
在使用C语言8年后,我现在才意识到scanf的这个“缺陷” 下面的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
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()
读取的输入缓冲区中的removes
。所以只需输出“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
}