在C语言中如何阅读scanf直到EOF?

在C语言中如何阅读scanf直到EOF?,c,scanf,eof,C,Scanf,Eof,我有这个,但一旦它达到了假设的EOF,它只是重复循环并再次扫描 int main(void) { char words[16]; while(scanf("%15s", words) == 1) printf("%s\n", words); return 0; } 您需要对照EOF检查返回值,而不是对照1 请注意,在您的示例中,您还使用了两个不同的变量名,words和word,只声明了words,而没有声明其长度,其长度

我有这个,但一旦它达到了假设的EOF,它只是重复循环并再次扫描

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

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

        return 0;
}

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

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

尝试:

while(scanf("%15s", words) != EOF)
您需要将
scanf
输出与
EOF

由于您在格式字符串中指定的宽度为
15
,因此最多读取15个字符。因此单词char数组的大小应该是
16
15+1
表示
null
char)。因此,声明如下:

char words[16];

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;
}

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

如果要循环阅读单词,请使用while:

while (scanf("%15s", word) == 1)
    printf("%s\n", word);
另外,正如其他人所指出的,您需要为单词数组指定一个足够大的大小,以满足您的scanf:

char word[16];
其他人建议测试EOF,而不是检查scanf匹配了多少项。这对于这种情况很好,在这种情况下,除非有EOF,否则scanf不能不匹配,但在其他情况下(例如尝试读取整数),scanf可能不匹配任何内容而不达到EOF(如果输入不是数字)并返回0

编辑


看起来你改变了你的问题来匹配我的代码,当我运行它时,它运行得很好——循环读取单词,直到达到EOF,然后退出。因此,您的代码中还发生了其他一些事情,可能与David为C用户建议的输入方式有关,这也会起作用

while ( gets(str) != NULL )

我想最好的办法是

int main()
{
    char str[100];
    scanf("[^EOF]",str);
    printf("%s",str);
    return 0;     
}

伙计,如果你使用的是Windows,按enter键并不能达到EOF,而是在控制台上按Crtl+Z键。这将打印“^Z”,表示EOF。 读取此值时函数的行为(EOF或Crtl+Z):


功能:输出:
scanf(…)EOF
获取()NULL
feof(stdin)1
getchar()EOF

是的,这比(char buf[1024];scanf(“%1023s”,buf)==1;)printf(“%s\n”,buf)要简单得多,除非您在某些情况下更改了前导、尾随和相邻空格的行为。在现实生活中,我会使用我想要的空格行为(这可能是OP想要的,也可能不是OP想要的-他们没有说),在单个字符上写一个循环,但这对于一个示例来说太单调乏味了。如果您使用的是scanf,那么无论如何,您都不能关心边缘案例行为或错误恢复。。。。你知道吗,这并不太乏味。重写示例。您的新示例更好,但它现在不是完全等同于我上面的一行代码吗?如果是这样的话,为什么要用15行替换一行(或者更可能是两行)?好吧,主要是因为我知道我的15行代码正是我想要的,而我不相信scanf会做我想要的。它的行为有太多奇怪的角落,特别是当涉及错误处理时。这是不对的。scanf返回成功扫描的输入字段数,从不返回EOF(-1)。因此,while循环是冗余的,它将在第一时间中断。@user411313否,scanf可以返回EOF,因为他正在使用!=第一次不会坏的。但是,在一般情况下,您还需要指定项目的数量,以便进行一些验证。@user411313:和C99§7.19.6.2/16都表示它可以返回EOF。这会产生相同的输出,[我是一个句子][我是][一个句子][一个句子],然后scanf再次开始。。。这个循环以字符串输入终止,因为所有字符(甚至是空字节)都被接受。如果转换使用的是数字类型(例如,
int d;while(scanf(“%d”,&d)!=EOF){…}
),那么如果输入中有一个非数字、非空白字符(例如字母或标点符号),您将得到一个无限循环。总的来说,问题中的样式-
while(scanf(“…”,&variable)==1)
是最好的。我想知道为什么这对OP不起作用。(也许)你在用什么输入?您是将文件重定向到stdin还是在控制台键入?如果是后者,你在使用什么操作系统,你是如何输入EOF的?嘿,谢谢你的回复,但是你试过这个吗?我意识到我把“!=”放在了我原来的帖子上,但我的意思是==,这给了我我想要的东西,当调用scanf时,我在那里键入一个句子,然后它循环并打印出单词,就像它应该的一样,然后它再次调用scanf,这是我不想要的。它叫它离开我没有办法打破循环。也许是我的编译器?但唯一的问题是在它打印出所有没有中断的单词后。@user315903:这就是为什么最好的办法是发布不起作用的代码,而不是尝试键入类似的内容。如果您的代码因您不了解的原因而无法正常工作,那么您不了解哪里出了问题,也无法相信自己能够保留问题的本质;它不会在空输入上永远循环。如果没有要读取的数据,
scanf()
将返回
EOF
,它不是
1
,因此循环应该停止。
的问题得到解决
while ( gets(str) != NULL )
int main()
{
    char str[100];
    scanf("[^EOF]",str);
    printf("%s",str);
    return 0;     
}