【问题标题】:While loop never exits for EOF循环永远不会退出 EOF
【发布时间】:2012-09-14 11:10:24
【问题描述】:

我正在用 C 编写自己的 shell,我需要检测 EOF(当我运行 ./myshell < commands.txt 时)

commands.txt 包含:

ls
pwd

它们都可以在程序中单独运行。但是当我用文本文件运行它时,我得到了一个无限循环。

在我的while(1) shell 循环中,我做的第一件事是:

if (feof(stdin)) { my_exit(); }

my_exit 很简单:

void my_exit() {
    printf("End of file! Bye\n");
    exit(0);
}

exit(0) 不会结束程序(和循环)吗?为什么我会得到

文件结束!文件结束!文件结束!文件结束!文件结束!文件结束!再见....等等

我也尝试过fgets == NULL 的方式。相同的循环

【问题讨论】:

  • 是的,exit(0) 绝对应该退出该过程。向我们展示更多代码。
  • 如果不查看更多代码很难判断,但您应该通过检查您正在使用的任何输入函数返回的值来检测文件结束。 feof()ferror() 用于找出输入操作失败的原因。如果输入错误,ferror() 将返回 true,feof() 将返回 false,这可能会导致无限循环。
  • 我已经添加了我的其余代码 - 我还尝试使用 fgets == NULL 进行此检测,仍然导致无限循环,没有退出。奇怪的是,它打印出退出文本......所以它正在点击那个函数,但 exit(0) 并没有结束程序。

标签: c while-loop infinite-loop eof


【解决方案1】:

你可以这样试试……

int a=1;
while(a)
{
    if (feof(stdin)) {
        a = 0;
    }
}
printf("End of file! Bye\n");
exit(0);

【讨论】:

  • 这将执行循环体的其余部分,即使它位于 EOF。为什么不直接使用break; 退出循环?
【解决方案2】:

问题在于feof() 会告诉您最后一次输入操作是否遇到 EOF。但是在下一次迭代之前你不会检查这个。因此,当您在 EOF 时,您执行 fgets() 然后尝试使用它返回的空结果。

发生的事情是你fork() 一个子进程,然后用一个空的命令名调用execvp()。这是失败的,所以子进程返回到循环的开头,并做同样的事情。同时,父进程调用my_exit()。所以每个子进程都会派生出自己的另一个子进程,然后退出。

【讨论】:

  • 所以,不要费心去捕捉execvp()的结果;如果返回,则失败。考虑报告失败,exit(1); 表示失败——所有这些都在代表子进程的块中。您还可以在提示符中包含当前进程 ID,至少作为调试措施。
  • 基本上,这个程序缺少很多错误检查。在玩具程序中忽略这一点很常见,但在这种情况下,它会帮助发现问题。您需要检查 fgets() 是否返回错误,以便跳过循环体的其余部分,并检查 execvp() 是否返回任何内容,这样您就不会在子进程中恢复循环。
【解决方案3】:

feof 的工作方式是,只要没有读取到达 EOF,它就会返回 false。 feof 本身不检查流,而是检查是否设置了 EOF 指示符,这在 fgets 等失败时发生。

在控制循环中使用 feof 确实不是一个很好的做法。

验证 EOF 的示例如下:

while( fgets(line, sizeof(line), fp) != NULL )
  fputs(line, stdout);

【讨论】:

    猜你喜欢
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多