fgets()和Ctrl + D,三次结束?

时间:2017-03-24 14:12:30

标签: c ubuntu eof

我不明白为什么我需要按 Ctrl + D 三次才能发送EOF。

此外,如果按Enter键,则只需要一个 Ctrl + D 来发送EOF。

如何进行更改以便仅使用一个 Ctrl + D 然后它可以检测到EOF?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 1024

int main(){
    char buffer[BUF_SIZE];
    size_t msgLength = 1;
    char *msg = malloc(sizeof(char) * BUF_SIZE);

    msg[0] = '\0';
    printf("Message: ");
    while (fgets(buffer, BUF_SIZE, stdin)){
        char *old = msg;
        msgLength += strlen(buffer);
        msg = realloc(msg, msgLength);

        strcat(msg, buffer);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:3)

你遇到的问题是终端没有EOF - 它们不是文件,所以“文件结尾”没有任何意义。相反,它们有EOT(传输结束 - Ctrl + D ),由于(快乐?)事故,它通常作为EOF注册到stdio。

UNIX上的文件通过返回0大小读取信号EOF,并且stdio将任何大小0读取视为EOF,无论它是否从文件读取。当且仅当输入缓冲区为空时,EOT才会立即返回终端,这将是0读取(在stdio中触发EOF)。

最简单的解决方案是不要担心 - 如果用户想在此处发出EOF信号,请让用户多次点击 Ctrl + D 。它应该只需要两个,除非你有奇怪的时间问题。

如果你真的想,你可以尝试弄清楚EOT是否被击中 - 如果fgets的结果没有填满缓冲区并且没有以换行结束,那么用户点击EOT来传输它,所以你可以测试它并打破循环。如果用户输入足够的数据来填充fgets缓冲区然后点击EOT,则会失败。如果用户“打字”太快以至于程序无法跟上(当程序实际上没有等待输入时EOT没有效果),它也会失败。我说“打字”,因为终端可能是伪终端,在另一端伪装非常快的输入(包括EOT)

答案 1 :(得分:1)

如果你将这一行添加到你的循环的第一行,在fgets之后,并运行程序,也许它会很有启发性:

printf("GOT: [%s]\n", buffer);

前两个 Ctrl + D 需要结束您输入的部分行,然后是第三个 Ctrl + D ,在目前为止的空行上,关闭输入。