C 当FEZE在输入中间遇到EOF时会发生什么?

C 当FEZE在输入中间遇到EOF时会发生什么?,c,C,手册页上说: fgets()在成功时返回s,在错误时返回NULL,或者在未读取字符时出现文件结尾时返回NULL 我编写了一个小的C文件,它调用fgets来测试它的行为。我特别想看看在输入了一些字符后出现EOF时会发生什么。我在bash上使用了eof组合键(Ctrl+D)。我必须按Ctrl+D两次才能返回FGET。它打印出输入的字符,直到我按Ctrl+D两次。输入某些字符后按Ctrl+D一次根本没有效果。如果在此之后输入一些字符,它们将存储在传递的数组中。为什么FGET会这样做?您描述的行为与FG

手册页上说:

fgets()在成功时返回s,在错误时返回NULL,或者在未读取字符时出现文件结尾时返回NULL


我编写了一个小的C文件,它调用fgets来测试它的行为。我特别想看看在输入了一些字符后出现EOF时会发生什么。我在bash上使用了eof组合键(Ctrl+D)。我必须按Ctrl+D两次才能返回FGET。它打印出输入的字符,直到我按Ctrl+D两次。输入某些字符后按Ctrl+D一次根本没有效果。如果在此之后输入一些字符,它们将存储在传递的数组中。为什么FGET会这样做?

您描述的行为与FGET无关。在第二次按ctrl-D键之前,shell不会关闭输入流

您应该发现,如果输入在至少读取了一些字符之后但在遇到换行符之前结束,
fgets
返回非null(指向提供的缓冲区的指针),并且提供的缓冲区将不包含换行符,但将以null终止

这正是
fgets
的文档所说的

例如


这就像从存储在磁盘上的文本文件中读取一样,该文件的最后一行末尾没有新行字符。的
fgets()
说明指定了它的功能,在本例中包括:

char*fgets(char*restrict s,int n,
文件*限制流)

fgets函数读取的数据最多比 n流指向的流中指定的字符 进入s指向的数组。不读取其他字符 在新行字符(保留)之后或在文件结尾之后。A. 在最后一次读取字符后立即写入空字符 进入阵列

fgets()
如果输入行太长而无法容纳,或者在文件结尾之前没有新行,则可以为您提供不带新行的字符串

从磁盘文件读取时,到达文件末尾时会出现文件结束情况。当您从交互式设备(如键盘)读取时,触发文件结束条件的方式不是C标准指定的。在UNIX类系统中,它是通过在一行开始键入控制D或在一行中键入Control D两次来触发的(尽管可以重新配置控制字符)。 这是否可能取决于实施情况

C99 7.19p2表示:

文本流是按顺序排列的字符序列 行,每行由零个或多个字符加上 终止新行字符。最后一行是否需要 终止新行字符是实现定义的


类Unix系统通常不需要尾随的新行字符。

但是如果我以前没有输入任何字符就按Ctrl+D键,fgets将返回。在这种情况下,我不需要输入两次。当当前行中没有字符时,ctrl-D的处理方式不同。在这种情况下,第一次对其设置关键帧时,它将关闭流。在解释行为的同时,我想知道如果在输入几个字符后遇到eof会发生什么。有没有一个好的方法来测试这一点?更好的是,除了手册页之外,还有其他地方可以正式记录这种行为吗?@batbrat:你的手册页文档有什么问题吗?我清楚地说,它们返回传入的指针,除非发生错误或在未读取任何字符时出现文件结尾。我已经查过ISO/IEC 9899:1999,我相信这是对描述的忠实改写。@Charles Bailey,谢谢你澄清这一点。我很抱歉延迟回复。至于手册页的事,我现在记忆犹新。我不清楚你想了解什么。您想了解当您键入Ctrl-D和其他控制键组合时,
fgets
的行为还是终端的典型行为?
#include <stdio.h>

int main(void)
{
    char buffer[200];

    char* ret = fgets(buffer, sizeof buffer, stdin);

    printf("exit code = %p\n", (void*)ret);

    if (ret != 0)
    {
        printf("read code = %s<--END\n", buffer);
    }

    return 0;
}
$ printf "no newline here->" | ./a.out
exit code = 0x7fff6ab096c0
read code = no newline here-><--END
$ printf "newline here->\nmore text\n" | ./a.out
exit code = 0x7fff6f59e330
read code = newline here->
<--END
$ printf "" | ./a.out
exit code = (nil)