【问题标题】:What happens when fgets encounters EOF in the middle of an input?当 fgets 在输入过程中遇到 EOF 时会发生什么?
【发布时间】:2012-01-14 10:50:16
【问题描述】:

手册页说:

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

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

【问题讨论】:

  • 我不清楚你想了解什么。您想了解fgets 的行为还是您在键入 Ctrl-D 和其他控制键组合时终端的典型行为?

标签: c


【解决方案1】:

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

【讨论】:

  • 但是如果我在之前没有输入任何字符的情况下按下 Ctrl+D,fgets 就会返回。在这种情况下我不需要输入两次。
  • 当当前行没有字符时,ctrl-D 的处理方式不同。在这种情况下,第一次键入时,它会关闭流。见en.wikipedia.org/wiki/Bash_%28Unix_shell%29
  • 在解释行为的同时,我想知道如果在输入几个字符后遇到 eof 会发生什么。有没有好的方法来测试这个?更好的是,除了手册页之外,还有其他地方可以正确且正式地记录此行为吗?
  • @batbrat:您的手册页文档有什么问题?我的明确表示,除非发生错误或在读取 no 字符时发生文件结尾,否则它们会返回传入的指针。我检查了 ISO/IEC 9899:1999,我相信这是对那里描述的忠实改写。
  • @Charles Bailey,感谢您澄清这一点。我很抱歉延迟回复。至于手册页的事情,我现在记不住了。
【解决方案2】:

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

这正是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)

【讨论】:

    【解决方案3】:

    这就像从存储在磁盘上的文本文件中读取最后一行末尾没有换行符一样。 C standardfgets() 的描述指定了它的作用,包括在这种情况下:

    char *fgets(char * restrict s, int n, FILE * restrict stream);

    fgets 函数最多读取比 stream 指向的流中由 n 指定的字符 到 s 指向的数组中。没有额外的字符被读取 在换行符(保留)之后或文件结尾之后。一种 在读取最后一个字符后立即写入空字符 进入数组。

    fgets() 如果输入行太长而无法容纳,或者如果在文件结尾之前没有换行符,则可以给你一个没有换行符的字符串。

    当您从磁盘文件中读取数据时,当您到达文件末尾时会出现文件结束情况。当您从交互式设备(如键盘)读取时,C 标准未指定触发文件结束条件的方式。在类 Unix 系统上,它通过在行首键入 Control-D 或在一行中间键入两次 Control-D 来触发(尽管控制字符可以重新配置)。

    这是否可能取决于实现。

    C99 7.19p2 说:

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

    类 Unix 系统通常不需要尾随换行符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 2021-11-09
      相关资源
      最近更新 更多