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

fgets() and Ctrl+D, three times to end?

我不明白为什么要按三下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] = '[=10=]';
    printf("Message: ");
    while (fgets(buffer, BUF_SIZE, stdin)){
        char *old = msg;
        msgLength += strlen(buffer);
        msg = realloc(msg, msgLength);

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

您遇到的问题是终端没有 EOF——它们不是文件,所以 "end of file" 没有任何意义。相反,他们有 EOT(传输结束 -- Ctrl+D),由于(快乐? ) 意外。

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

最简单的解决方案是不用担心 - 如果用户愿意,只需让他们多次按 Ctrl+D在这里发出 EOF 信号。它应该只需要两个,除非你有奇怪的时间问题。

如果您确实想要,您可以尝试确定是否命中了 EOT——如果 fgets 的结果没有填充缓冲区并且没有以换行符结尾,则用户命中了 EOT 来传输它,因此您可以对此进行测试并跳出循环。如果用户输入的数据恰好足以填充 fgets 缓冲区然后命中 EOT,则此操作失败。如果用户 "typing" 太快以至于程序无法跟上,它也可能会失败(程序实际上并未等待输入时的 EOT 无效)。我说 "typing" 因为终端可能是一个伪终端,在另一端(包括 EOTs)伪造非常快的输入

如果将此行添加为循环中的第一行,在 fgets 和 运行 程序之后,也许它会很有启发性:

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

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