#include <stdio.h>
int main()
{
int sum=0;
char s[10];
while(scanf("%[^\n]s", s)!=EOF)
{
printf("%s", s);
}
return 0;
}
这个while循环落入任何字符串输入的无限循环。
答案 0 :(得分:6)
鉴于
while(scanf("%[^\n]s", s)!=EOF)
{
printf("%s", s);
}
你问“为什么这个c程序会陷入无限循环?”
因此,您必须了解scanf()
的工作原理。 scanf()
使用您的格式字符串来解析stdin
的输入,这是一个流,逐个字符地提供。
假设您在stdin
中有以下内容:
foo\n
bar\n
<<EOF>>
现在,您的格式字符串具有此转换%[^\n]
,这意味着“匹配除换行符之外的任何内容并复制到char缓冲区”。跟随它的s
只是一个文字s
,因为它前面没有%
...所以它会匹配文字s
,如果有的话一。换句话说,这没关系。
现在,第一次调用scanf()
,它将匹配foo
并使用它。它返回1
,因为它匹配一个元素。之后,stdin
看起来像这样:
\n
bar\n
<<EOF>>
请注意,不匹配的换行符仍然存在。您的下一个电话会以格式字符串开头,以匹配除换行符之外的任何内容,但下一个字符是换行符。 scanf()
不匹配,因此会返回0
。它无法返回EOF
,因为您可以看到,EOF
尚未到达。这是你的无限循环。
所以,你必须修复你的格式字符串。首先,删除从不匹配任何内容的s
。它在这里并没有真正受到伤害,但它仍然是错误的。然后,您可以利用scanf()
的空白匹配。空格是 space , tab 或 newline 。如果您的格式字符串包含空格,scanf()
将匹配与一样多的空格(这也可以是无)。因此,一个简单的解决方法就是用空格开始你的格式字符串,这将“吃掉”剩下的换行符:
while(scanf(" %[^\n]", s)!=EOF)
{
printf("%s", s);
}
现在这仍然是危险代码,因为只要没有换行符,[^\n]
就匹配任意数量的字符,但是你的缓冲区只有9个字符的空间加上终止{{1 }}。因此,您必须告诉0
不要超过该限制,这可以通过将数字放在scanf()
和转换规范之间来完成:
%
此代码将以安全的方式执行您想要的操作,但假设您希望匹配更具体的内容,例如:数字,你得到一些意想不到的输入:等待while(scanf(" %9[^\n]", s)!=EOF)
{
printf("%s", s);
}
,你会再次拥有无限循环,因为有输入不匹配,所以你永远不会到达EOF
(如上面有无与伦比的换行符)。因此,请始终检查成功匹配的数量。在这里你只需要一个匹配,所以循环应该如下所示:
EOF
实际上,要阅读整行,您不需要while (scanf(" %9[^\n]", s) == 1)
{
printf("%s", s);
}
,只需使用scanf()
就会更容易。您的代码可能看起来很简单(换行符也会被读入fgets()
):
s
请注意此处的第二个参数while (fgets(s, 10, stdin))
{
printf("%s", s);
}
:10
会自动说明终止fgets()
字符,因此您只需指定缓冲区的大小。
最后一个提示:当没有格式化时,这可能甚至更简单而不使用0
:
printf()
答案 1 :(得分:-1)
int main()
{
int sum = 0;
char s[10];
int ret = scanf("%[^\n]s", s);
while (ret != EOF)
{
printf("%s", s);
memset(s,0,10);
ret = scanf("%[^\n]s", s);
}
return 0;
}
通过调试,您可以看到while块中的第二个ret值为0,即不等于EOF,因此无限循环。
man scanf:
返回值
成功完成后,这些函数将返回成功匹配和分配的输入项的数量;如果早期匹配失败,此数字可以为零。
这意味着另一个scanf匹配失败,除了第一个。
但为什么?
stdio有缓存,匹配只从stdin读取“\ n”,但是当你输入“Enter”时,它输入“\ n \ r”,所以,“\ r”将在stdin中缓存并成为其他scanf的输入值,但无法匹配输入,因此匹配失败。并且scanf返回0,并转到无限循环。
但是如果你只为每个输入输入“\ n”,那就OK了!
您可以按“Alt”并同时按“0”+“1”+“0”,然后释放“Alt”,控制台只会输入“\ n”,您将获得正确的结果,程序会好的,不会进入无限循环!
这是我的测试结果:enter image description here