Azi*_*med 1 c loops scanf while-loop
#include <stdio.h>
int main()
{
int sum=0;
char s[10];
while(scanf("%[^\n]s", s)!=EOF)
{
printf("%s", s);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个while循环落入任何字符串输入的无限循环.
小智 6
特定
while(scanf("%[^\n]s", s)!=EOF)
{
printf("%s", s);
}
Run Code Online (Sandbox Code Playgroud)
你问"为什么这个程序会陷入无限循环?"
因此,你必须了解它的scanf()工作原理.scanf()使用您的格式字符串来解析输入stdin,这是一个逐字符递送的流.
假设您有以下内容stdin:
foo\n
bar\n
<<EOF>>
Run Code Online (Sandbox Code Playgroud)
现在您的格式字符串具有此转换%[^\n],这意味着"匹配除换行符之外的任何内容并复制到char缓冲区".在s下面,这只是一个文字s,因为它没有一个%在它前面...所以它会匹配文字s,如果有一个.换句话说,这并不重要.
现在,scanf()第一次打电话给你,它会匹配foo并消耗它.它返回,1因为它匹配一个元素.之后,stdin看起来像这样:
\n
bar\n
<<EOF>>
Run Code Online (Sandbox Code Playgroud)
请注意,无与伦比的换行仍然存在.您的下一个呼叫将以格式字符串开头,以匹配除换行符之外的任何内容,但下一个字符是换行符.scanf()什么都不匹配,因此返回0.它无法返回EOF,因为您可以看到,EOF尚未到达.这是你的无限循环.
所以,你必须修复你的格式字符串.首先,删除s永远不匹配的东西.它在这里并没有真正受到伤害,但它仍然是错误的.然后,您可以采取的优势空白匹配的scanf().空格是空格,制表符或换行符.如果您的格式字符串包含空格,那么scanf()将匹配尽可能多的空格(这也可以是空格).因此,一个简单的解决方法就是用空格开始你的格式字符串,这将"吃掉"剩下的换行符:
while(scanf(" %[^\n]", s)!=EOF)
{
printf("%s", s);
}
Run Code Online (Sandbox Code Playgroud)
现在这仍然是危险的代码,因为[^\n]只要没有换行符就匹配任意数量的字符,但是你的缓冲区只有9个字符的空间加上终止0.所以你必须告诉scanf()不要匹配超过那个限制,这可以通过%在转换规范之间加上数字来完成:
while(scanf(" %9[^\n]", s)!=EOF)
{
printf("%s", s);
}
Run Code Online (Sandbox Code Playgroud)
这段代码会以安全的方式执行您想要的操作,但假设您想要匹配更具体的内容,例如数字,并且您会收到一些意外的输入:通过等待EOF,您将再次拥有无限循环,因为有输入不匹配,因此您永远无法达到EOF(如上所述,具有无与伦比的换行符).因此,请始终检查成功匹配的数量.在这里你只需要一个匹配,所以循环应该如下所示:
while (scanf(" %9[^\n]", s) == 1)
{
printf("%s", s);
}
Run Code Online (Sandbox Code Playgroud)
在实践中,阅读整行,你不需要scanf(),只是使用fgets()会更容易.您的代码看起来很简单(新行也将被读入s):
while (fgets(s, 10, stdin))
{
printf("%s", s);
}
Run Code Online (Sandbox Code Playgroud)
注意10这里的第二个参数:fgets()自动计算终止0字符,所以你只需给它缓冲区的大小.
只是最后提示:这可能是更简单的不使用printf()时,有没有格式的事情:
while (fgets(s, 10, stdin))
{
fputs(s, stdout);
}
Run Code Online (Sandbox Code Playgroud)