【问题标题】:Why does EOF behave differently in fgets and read为什么 EOF 在 fgets 和 read 中的行为不同
【发布时间】:2016-06-02 20:56:36
【问题描述】:
#include <stdio.h>

#define MAXLINE 4096

int 
main(int argc, char **argv)
{
    char           *s;
    char            buf[MAXLINE];

    s = fgets(buf, MAXLINE, stdin);    // here, if replaced with read(0, buf, MAXLINE);        

    return 0;
}

输入是:12ctrl+d

  1. fgets直到再次输入ctrl+d才返回(即:12ctrl+dctrl+d)。为什么 fgets 在遇到第一个 EOF 时不返回? 似乎 12ctrl+d 不起作用。

  2. 但是当s = fgets(buf, MAXLINE, stdin);read(0, buf, MAXLINE);替换时read会返回(输入也是:12ctrl+d)。

【问题讨论】:

  • 因为它们是不同的功能?为什么您希望它们表现相同?
  • 我认为 fgets 在按照手册遇到 EOF 时应该返回,但输入 12ctrl+d fgets 不会返回。 fgets() 从流中最多读入一个小于 size 的字符并将它们存储到 s 指向的缓冲区中。在EOF 或换行符后停止阅读。
  • 该标准没有指定何时检测到 eof。尝试从 shell 中的文件重定向 stdin,您将看到不同的行为。 Itr 是控制台缓冲的问题。
  • 根据手册,fgets()从流中最多读入一个小于size的字符,并将它们存储到s指向的缓冲区中。 在 EOF 或换行符后停止读取。

标签: c linux fgets eof


【解决方案1】:

在终端点击CTRL+d

  • 只是意味着立即刷新stdin(输入缓冲区)中的所有字符
  • 它不会在 stdin 上触发 EOF 条件
    (除非当前行/缓冲区同时为空。)

所以在运行程序时按 CTRL+D,

  • 如果您连续执行两次,被阻止的 fgetc() 将返回。
    第一次 = 刷新当前缓冲的字符,
    2nd = 刷新空缓冲区;即EOF 条件对fgetc() 有效并且它返回
  • 如果您在空行上执行一次,则被阻止的 fgetc() 将返回。
    刷新已经为空的 stdin 缓冲区,即 EOF 条件对 @987654330 有效@ 并返回。
  • blockedread() 在输入刷新后立即返回。

查看此question的答案以了解更多详情。

【讨论】:

  • 此答案与链接到的答案同样错误:没有 EOF 字符。另外:您的意思是哪个“缓冲区”:(伪)终端驱动程序使用的缓冲区,还是stdio的缓冲区?
  • 谢谢@wildplasser。我已经更新了答案以避免歧义和不正确的术语。我希望它现在很清楚。
【解决方案2】:

在常见的实现中,fgets 是基于围绕read 的循环。如果您调用fgets,它会在内部调用read。键入 12Ctrl+D 会使read 将两个字符“12”返回给fgets。这还没有形成完整的线路,所以fgets 再次调用read。由于我们是从终端设备读取,而不是从文件读取,read 等待您输入更多数据。如果再次键入 Ctrl+Dread 返回 0 个字符,fgets 将其解释为文件结尾并返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    相关资源
    最近更新 更多