我有这段代码,但是一旦它到达了预定的EOF(文件结束符),它就会重复循环并再次使用scanf。
int main(void)
{
char words[16];
while(scanf("%15s", words) == 1)
printf("%s\n", words);
return 0;
}
尝试:
while(scanf("%15s", words) != EOF)
你需要将scanf
的输出结果与EOF
进行比较。15
,因此你最多只会读取15个字符。所以这个字符数组应该有16
个大小(15 +1
用于null
字符)。请将其声明为:char words[16];
int d; while (scanf("%d", &d) != EOF) { … }
),那么如果输入中有非数字、非空格字符(例如字母或标点符号),则会得到一个无限循环。总的来说,问题中的风格——while (scanf("…", &variable) == 1)
是最好的。我想知道为什么这对 OP 不起作用。(也许是 为什么分叉我的进程会导致我的文件无限读取?) - Jonathan Lefflerscanf通常会带来很多麻烦,以下是两种更好的替代方案。第一种方案基本上是你代码的直接翻译。虽然它更长,但你可以清晰地看到它的功能,不像scanf那样难以理解。
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char buf[1024], *p, *q;
while (fgets(buf, 1024, stdin))
{
p = buf;
while (*p)
{
while (*p && isspace(*p)) p++;
q = p;
while (*q && !isspace(*q)) q++;
*q = '\0';
if (p != q)
puts(p);
p = q;
}
}
return 0;
}
这里有另一个版本。通过检查很难看出它的作用,但是如果一行超过1024个字符,它不会崩溃,因此这是我在生产中使用的代码。(好吧,实际上我会使用tr -s '[:space:]' '\n'
,但这是如何实现类似功能的方法。)
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int ch, lastch = '\0';
while ((ch = getchar()) != EOF)
{
if (!isspace(ch))
putchar(ch);
if (!isspace(lastch))
putchar('\n');
lastch = ch;
}
if (lastch != '\0' && !isspace(lastch))
putchar('\n');
return 0;
}
for (char buf[1024]; scanf("%1023s", buf) == 1;) printf("%s\n", buf);
简单多了,只是在某些前导、尾随和相邻空格的情况下改变了行为。 - Roger Pate你的代码会循环读取一个单词,然后退出。所以如果你输入多个单词,它只会读取第一个单词并退出;而如果你输入空内容,它将永远循环下去。无论哪种情况,它都只会打印来自未初始化内存的随机垃圾数据。这显然不是你想要的结果,那么你想要什么呢?如果你只想读取和打印第一个单词(如果存在),请使用 if 语句:
if (scanf("%15s", word) == 1)
printf("%s\n", word);
while (scanf("%15s", word) == 1)
printf("%s\n", word);
此外,正如其他人所指出的那样,您需要为scanf分配足够大的数组大小:
char word[16];
scanf()
将返回EOF
,它不是1
,因此循环应该停止。 - Jonathan Leffler如果您使用的是Windows系统,按下回车键并不会触发EOF
,而是需要在控制台中按下Crtl+Z,这将打印出"^Z",表示EOF
。以下是读取EOF
或Crtl+Z时函数的行为:
函数 | 输出 |
---|---|
scanf(...) |
EOF |
gets(<variable>) |
NULL |
feof(stdin) |
1 |
getchar() |
EOF |
EOF
而不是 1
进行比较。words
和 word
,只声明了 words
,并没有声明它的长度,它应该是 16,以适应读入的 15 个字符加上一个 NUL
字符。我想最好的方法是...
int main()
{
char str[100];
scanf("[^EOF]",str);
printf("%s",str);
return 0;
}
对于C语言用户,这也是适用的
while ( gets(str) != NULL )
gets
存在的问题在于它可以写入超出分配缓冲区末尾的内容。 - Ben Voigt
stdin
还是在控制台键入?如果是后者,您使用的操作系统是什么,如何键入EOF? - David Thornley