2017-03-22 10 views
0

私は最初にUnixパイプラインからデータを受け取り、ユーザに入力を促すアプリケーションを書いています。私が理解できないように見えるのは、パイプラインからの入力がユーザに入力を促す前に適切に閉じるように見えない理由です。私はここで非常に初歩的な何かを逃しているように感じる。C - stdin、unix pipeline、EOF

私は、標準入力をフラッシュするためのすべての例を試しましたが、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 
$ 

どのようにそれは(キーボード入力するためのもの)は、第2の関数fgets()は、バッファに触れることがないことをすることができますか?

このMCVEは、OSXとLinuxで同じ結果を得てコンパイルされています。

+0

のように、stdinをパイプ処理されても別にターミナルを開く必要があり、キーボード入力を取得できべき 'のcalloc()' BUFSZ + 1ので、あなたは '\ 0 'のためのスペースを持っていますならばそのバッファーを満たすのに十分な長さの行を読み込みます。 –

+2

'stdin'は閉じられません(' fgets'が 'NULL'を返すので)、むしろユーザー入力のために再オープンされません。 – Kninnug

+0

@ChrisTurner 'fgets'はそれを可能にします:実際のバッファサイズを伝えるだけです。 –

答えて

5

stdinがパイプの場合、stdinは端末ではありません。あなたがパイプの終わりに達すると、それはそれです!それはstdinの終わりです。 stdinがパイプを止めて、何か他のものになり始めたら、魔法のような変身を期待しています。期待しないでください。まだパイプです。そして、EOFが発生しました。パイプの場合、EOFは永続的な条件です。いったんEOFを叩くと、あなたはそれ以上何も得られません。

fgetsの戻り値をすべて時間に確認してください。あなたはEOFにあるので、最後のものがnullを返すことがわかります。読みたい

プログラムはFILE *tty = fopen("/dev/tty", "r");

+0

ああ、確かに解決策のようです。私はここで何か初心者が欠けていたことを知っていた。ありがとうございました! –