【问题标题】:fgets(): Ok by console, Bad by pipefgets():控制台确定,管道失败
【发布时间】:2012-09-21 08:39:55
【问题描述】:

执行以下 C 代码

#include <stdio.h>
int main(int argc, char **argv) {
  char stdinput[10];
  while (1) {
    fgets(stdinput, 10, stdin);
    fputs(stdinput, stdout);
  }
}

产生:

通过控制台:

./a.out
input
input

然后它等待更多输入。也就是说,它将标准输入回显到标准输出,类似于cat

通过管道:

echo input | ./a.out
input
input
input
[...]

启动后,它会自行淹没控制台,无需交互。

这个示例程序正是我用于测试的程序;这不是削减。 我希望这两个测试的行为方式相同。发生了什么事?

【问题讨论】:

  • 再一次完美地证明了为什么没有保护的输入操作总是错误的......你必须永远忽略输入操作的结果。

标签: c linux io pipe


【解决方案1】:

一旦到达EOFfgets 立即返回 NULL,无需等待输入(或修改缓冲区)。因此,它将无限循环。在您的管道案例中,echo 将在写入 "input\n" 后关闭管道,从而导致 EOF。

将您的 fgets 呼叫更改为

if(fgets(stdinput, 10, stdin) == NULL)
    break;

【讨论】:

    【解决方案2】:

    您可以通过 fgets 调用替换您的循环条件,给出:

    #include <stdio.h>
    int main(int argc, char **argv) {
      char stdinput[10];
      while (fgets(stdinput, 10, stdin)) {
        fputs(stdinput, stdout);
      }
    }
    

    这将循环直到你得到一个 EOF,在这种情况下 fgets() 返回 NULL 就像 @nneonneo said 一样。但是在这种情况下,您不必破坏您的while()

    【讨论】:

      【解决方案3】:

      [注意:解决了错误的问题。]

      http://sweslo17.blogspot.tw/2012/04/c-standard-input-redirection.html

      fgets() 之后,您可以添加以下代码以再次恢复stdin 以解决管道问题。

      freopen("/dev/tty","rb",stdin);
      

      【讨论】:

      • 嗯,这看起来并没有解决正确的问题。不过,我已经对其进行了清理,以向您展示如果它确实解决了正确的问题,我希望它的外观。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 2016-01-23
      • 1970-01-01
      • 2019-04-11
      • 2022-11-17
      • 2020-06-05
      相关资源
      最近更新 更多