星期一, 4月 02, 2012

[C] standard input redirection

這禮拜在看給學生的spec時由CA大大發現了一個問題:
平常程式執行,會用pipe(|)或是(<)的方式將檔案塞到程式的stdin中,例如

./read_file < test.data

這樣就會把test.data這個檔案變成程式的stdin

問題是如果在輸入完檔案之後還要能夠讓使用者在console輸入呢?
底下是個範例程式碼:


#include<stdio.h>

int main()

{

        char buffer[1000];

        while(fgets(buffer,1000,stdin))

        {



        }

        fgets(buffer,1000,stdin);

        printf("%s",buffer);

        return 0;

}



我們發現不管怎麼樣,底下的fgets(buffer,1000,stdin);就是不會執行。
剛開始以為是因為EOF卡在stdin裡,所以使用fpurge(),fflush(),clearerr()之類的函式,結果都沒變

仔細想想,當初在寫SP作業的shell時用過一個dup2()這個函式
所以這個時候的stdin應該已經被這個檔案的file descriptor取代掉了

真相大白!!!

所以現在的目標就是找回失去的stdin
修改後的程式碼如下:


#include<stdio.h>

int main()

{

        char buffer[1000];

        while(fgets(buffer,1000,stdin))

        {



        }

        stdin = fopen("/dev/tty","rb");

        fgets(buffer,1000,stdin);

        printf("%s",buffer);

        return 0;

}


6 則留言:

Terces Tsai 提到...

我自己的做法是:
if( feof( stdin)) {
clearerr( stdin);
}

這樣就能把stdin 繼續使用了

CA 提到...

如果是用 > 或 | 的方式,stdin用clearerr會清不掉EOF

羅澤揚 提到...

應該跟我推測的一樣,這時候的clearerr清到的是檔案的EOF。file descriptor 沒有改變

fbukevin 提到...

看到 CA 和 SP ...

剛剛卡這個問題好久,找了很多資料終於找到這裡解決了!

Terces Tsai 提到...

Sorry I got a wrong!

匿名 提到...

You are solved my problems. Appreciate.