【问题标题】:Detecting EOF with fgets() where filesteam is stdin使用 fgets() 检测 EOF,其中 filesteam 是标准输入
【发布时间】:2015-08-16 22:24:37
【问题描述】:

一点背景知识,我正在编写一个玩游戏“盒子”的程序,它在 linux 命令行中运行并用 C 编写。有一个提示等待用户输入,然后用 fgets() 读取并解释等等。

作为任务规范的一部分,如果我到达“等待用户输入时文件结束”,我必须返回一个特定错误。我知道 fgets() 在到达 EOF 时返回 null ...但是说我有

fgets(input,max_buffer,stdin);

在提示循环中,如果用户过早退出,使用 CTRL+C 或 CTRL+D 是否意味着 input == NULL?

我什至可以检测到用户何时使用 fgets 执行此操作?

只是想解决这个问题,在此先感谢您的帮助。

(操作系统:UNIX) (编译器:gcc - c90)

【问题讨论】:

  • Ctl-C 杀死程序,所以fgets 永远不会返回。 Ctl-D 导致文件结束条件。 man fgets

标签: c null eof fgets


【解决方案1】:

来自herefgets

从流中读取字符并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件结尾,以先发生者为准。

换行符使 fgets 停止读取,但它被函数视为有效字符并包含在复制到 str 的字符串中。

在复制到 str 的字符之后会自动附加一个终止空字符。

所以,fgets 将在用户输入 CTRL-D(文件结尾)时返回,当遇到 \n(换行符)时。 默认情况下 CTRL-C 将完全终止您的程序。

如果您想抓住 CTRL-C 并优雅地退出,您可以:

#include <signal.h>

void intHandler(int dummy) {
    //graceful CTRL-C exit code.
}

int main(void) {
    signal(SIGINT, intHandler);
    //your code
}
    

【讨论】:

  • 从技术上讲,说 Control-C 终止您的程序是错误的。它可以,但这只是默认行为,可以根据您的演示进行更改。 SIGTERM 和 SIGKILL 是专门为终止进程而设计的,SIGKILL 几乎可以保证工作,因为它不能被阻止或忽略。
  • @SevenBits,感谢您对我的疏忽做出的回应。我的回答已更新以反映您的观点。
【解决方案2】:

文档(C99 §7.19.7.2):

如果成功,fgets 函数将返回 s。如果遇到文件结尾并且没有字符被读入数组,则数组的内容保持不变并返回一个空指针。如果在操作过程中发生读取错误,则数组内容不确定,返回空指针。

因此,如果出现文件结尾,但已读取字符,fgets 将不会返回 NULL。如果在读取任何输入之前发生 EOF,它将返回 NULL

您可以使用 feofferror 函数区分 EOF 和读取错误。

【讨论】:

    【解决方案3】:

    当最终用户使用 Ctrl+C 永久退出时,您的程序会立即失去控制,这意味着您无法从 fgets 获得任何进一步的输入,甚至没有 NULL。

    另一方面,Ctrl+D 在不关闭程序的情况下关闭输入流,因此 fgets 调用会得到 NULL 结果。

    您可以将程序设置为通过处理信号来处理 Ctrl+C,但这种处理将发生在输入循环之外。

    【讨论】:

    • 我的印象是,如果发生错误,则返回空指针,否则 control-c 不会被视为错误。
    • @l'L'l Ctrl+C 不是 I/O 错误,它作为关闭进程的信号被越界处理。
    • 啊,好吧...我一定是在回想起 Ascii ETX 天! :)
    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2012-11-06
    相关资源
    最近更新 更多