2017-03-22 113 views
0

我正在写一个应用程序,它首先从unix管道接收数据,然后提示用户输入。我似乎无法弄清楚的是,为什么来自管道的输入在提示用户输入前似乎没有正确关闭。这感觉就像我在这里错过了一些非常基本的东西。C - stdin,unix管道和EOF

我已经尝试所有示例刷新stdin呈现here没有成功。 This也似乎潜在相关,但我没有设法提取任何相关的答案。

#include <stdio.h> 
#include <stdlib.h> 

#define BUFSZ 1024 

int main(void) { 

    char *buf = calloc(BUFSZ, sizeof(char)); 

    while(fgets(buf, BUFSZ, stdin)) { printf("Pipe input: %s", buf); } 

    printf("Enter input: "); 
    fgets(buf, BUFSZ, stdin); 
    printf("User input: %s", buf); 

    free(buf); 
    return 0; 
} 

实施例的使用和输出:

$ cat testdata2 | ./a.out 
Pipe input: testdata testdata 
Pipe input: testdata testdata2 
Pipe input: testdata testdata3 
Pipe input: testdata testdata4 
Pipe input: testdata testdata5 
Pipe input: testdata testdata6 
Pipe input: testdata testdata7 
Enter input: User input: testdata testdata7 
$ 

它如何可以是第二与fgets()(用于键盘输入)从不接触缓冲器?

此MCVE已在OSX和Linux上编译测试,结果相同。

+0

你应该'释放calloc()'BUFSZ + 1让你拥有了'\ 0'空间,如果您曾经阅读过足够长的时间来填补缓冲区。 –

+2

你的问题不在于'stdin'没有关闭(它的确如此,因为fgets'返回NULL),而是它不会重新打开以供用户输入。 – Kninnug

+0

@ChrisTurner'fgets'允许:你只需告诉它实际的缓冲区大小。 –

回答

5

如果stdin是管道,那么stdin不是终端。当你到达管道的尽头时,就是这样!这是stdin的结尾。你正期待着一种神奇的转变,其中stdin不再是管道,并开始成为别的东西。不要期望这一点。它仍然是管道。 EOF发生了。对于管道,EOF是一个永久性条件。一旦你击中EOF,你永远不会得到更多。

请检查fgets的返回值每时间。你会看到最后一个返回null,因为它在EOF。

程序,要读管道stdin并同时获得键盘输入必须单独打开终端,如FILE *tty = fopen("/dev/tty", "r");

+0

啊,是的,这似乎确实是解决方案。我知道我在这里错过了一些基本的东西。谢谢! –