你怎么读C中的scanf直到EOF?

JJR*_*thm 30 c scanf eof

我有这个但是一旦它到达假定的EOF它再次重复循环和scanf.

int main(void)
{
        char words[16];

        while(scanf("%15s", words) == 1)
           printf("%s\n", words);

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

cod*_*ict 20

尝试:

while(scanf("%15s", words) != EOF)
Run Code Online (Sandbox Code Playgroud)

你需要比较scanf输出EOF

由于您15在格式字符串中指定宽度,因此最多可以读取15个字符.所以char数组的单词应该是大小的16(15 +1对于nullchar).所以声明为:

char words[16];
Run Code Online (Sandbox Code Playgroud)

  • 这个不对.scanf返回成功扫描的输入字段数,从不EOF(-1).因此你的while循环是多余的,它会在第一时间中断. (3认同)
  • @ user411313不,scanf可以返回EOF,因为他正在使用!=它不会在第一次中断.但是,在一般情况下,您还需要分配项目的数量,以便进行一些验证. (3认同)
  • @ user411313:[man scanf](http://www.google.com/search?q=man+scanf)和C99§7.19.6.2/ 16都说它可以返回EOF. (3认同)
  • 该循环以字符串输入终止,因为所有字符(甚至空字节)都被接受。如果转换使用数字类型(例如 `int d; while (scanf("%d", &d) != EOF) { … }`),那么如果存在非数字,您将得到无限循环,输入中的非空白字符(例如字母或标点符号)。总的来说,问题中的风格 - `while (scanf("...", &variable) == 1)` 是最好的。我想知道为什么这对OP不起作用。(也许[为什么分叉我的进程会导致我的文件无限读取?](/sf/ask/3507769471/)) (2认同)

zwo*_*wol 5

Scanf 几乎总是比它的价值更麻烦。这里有两种更好的方法来做你想做的事情。第一个或多或少是对代码的直接翻译。它更长,但您可以查看它并清楚地看到它的作用,这与 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;
}
Run Code Online (Sandbox Code Playgroud)

这是另一个版本。通过检查看它做了什么有点困难,但是如果一行的长度超过 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;
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*odd 5

您的代码会循环直到读取一个单词,然后退出。因此,如果你给它多个单词,它会读取第一个单词并退出,而如果你给它一个空输入,它将永远循环。无论如何,它只会打印未初始化内存中的随机垃圾。这显然不是你想要的,但是你想要什么?如果您只想读取并打印第一个单词(如果存在),请使用 if:

if (scanf("%15s", word) == 1)
    printf("%s\n", word);
Run Code Online (Sandbox Code Playgroud)

如果你想循环直到你能读到一个单词,请使用 while:

while (scanf("%15s", word) == 1)
    printf("%s\n", word);
Run Code Online (Sandbox Code Playgroud)

另外,正如其他人指出的那样,您需要为单词数组提供足够大的大小以适合您的 scanf:

char word[16];
Run Code Online (Sandbox Code Playgroud)

其他人建议测试 EOF,而不是检查 scanf 匹配的项目数。对于这种情况来说这很好,除非存在 EOF,否则 scanf 不会失败,但在其他情况下(例如尝试读取整数)则不太好,其中 scanf 可能在未达到 EOF 的情况下不匹配任何内容(如果输入不是) t 一个数字)并返回 0。

编辑

看起来你改变了你的问题以匹配我的代码,当我运行它时工作正常 - 循环读取单词直到达到 EOF 然后退出。所以你的代码发生了其他事情,可能与你如何按照大卫的建议向其提供输入有关

  • @user315903:这就是为什么最好的想法是发布不起作用的代码,而不是尝试输入类似的代码。如果你的代码由于你不理解的原因而无法工作,那么你就不明白出了什么问题,并且不能相信自己能够保留问题的本质。 (2认同)

Bri*_*ell 0

EOF您需要对照而不是对照检查返回值1

请注意,在您的示例中,您还使用了两个不同的变量名称 和wordsword仅声明了words,并且没有声明其长度,该长度应为 16 以适应读入的 15 个字符加上一个NUL字符。