2015-05-23 81 views
5

當我使用命令行中的MyProgram < cl.txt命令將文件重定向到stdin時,scanf s不會等待我按Enter鍵。scanf如何確定是否阻止?

但是,當我在程序中使用scanf而沒有這樣做時,它會阻止,直到按下Enter鍵。

它究竟如何確定?是否繼續閱讀流,直到遇到\n?還是真的等着我按下一個鍵?

當我不寫任何東西並按下回車鍵時,它並不會停止任何操作,而是繼續詢問。我很困惑。

+1

有了'MyProgram

回答

6

scanf剛剛從其輸入流中讀取。如果輸入流是一個管道,並且管道的另一端與tty相關聯(通過按鍵盤上的鍵交互輸入數據通常是這種情況),scanf將在讀取數據後立即返回完成其格式字符串(或無法匹配它)。但是,如果tty處於熟化模式(這是默認模式,並且除非您花費一些努力將tty置於原始模式,則應假定它正在烹飪您輸入的內容),不會將任何數據寫入管道直到你打回來。

換句話說,這不是你的scanf阻塞。 (嗯,它是阻塞的,但它不是經驗延遲的來源。)相反,tty驅動程序正在等待您在將任何數據傳遞到您的程序之前返回。

+0

當我按下回車鍵而不輸入任何內容時,操作系統會忽略該輸入還是scanf本身? –

+0

@InsignificantPerson我不認爲scanf會忽略輸入,它只需要更多的輸入,並且由於輸入緩衝區中沒有更多數據,stdin會阻塞,直到數據到達。 – Suma

+1

@InsignificantPerson它取決於格式字符串,但通常格式字符串是這樣的,scanf忽略前導空格。在這種情況下,當scanf繼續查找數據以匹配格式字符串時,會讀取(但忽略)單行換行符。 –

2

當您調用scanf時,它立即等待輸入。在第一個例子中,輸入是以「cl.txt」的形式提供的。在你的第二個例子中,直到你按下一個鍵才能提供輸入。同步IO將在其執行線程上阻塞,直到它接收到輸入。

5

是否繼續閱讀流,直到遇到'\ n'?

通常stdin處於行緩衝模式(_IOLBF,見setvbuf)。當緩衝區是空的,標準輸入等待一個全新的行,直到按Enter鍵進入,即等待和\n插入緩衝:

在輸入時,緩衝區被填充到下一個換行符當請求輸入操作並且緩衝區爲空時。

注:控制檯(終端)是最常見的實現本身就是一個緩衝,並且不發送任何數據流,直到你按下回車 - 這允許你編輯的數據(如使用刪除和退格鍵),然後再將它們發送給應用程序。因此,即使在stdin一側沒有緩衝(例如執行setvbuf(stdin, NULL, _IONBF, 0)時),scanf仍可能會一直等到按下Enter鍵。