2017-03-22 114 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

啊,是的,這似乎確實是解決方案。我知道我在這裏錯過了一些基本的東西。謝謝! –