2015-11-02 36 views
1

我試圖完成練習1-9以K & R和我想出了這一點:K&R運動1.9 - 程序中無限循環

#include <stdio.h> 

/* this program will trim each group of spaces down to a single space */ 
int main() 
{ 
    int c, lastCharblank; 
    lastCharblank = 0; 

    while ((c = getchar()) != EOF) { 
     if (c != ' ' || !lastCharblank) 
      putchar(c); 

     lastCharblank = (c == ' '); 
    } 

    putchar('\n'); 

    return 0; 
} 

,同時通過bash命令行運行的程序,我能夠輸入文本(「修復這些空間」),然後輸入cntl-d來發送EOF信號。該程序返回所有更正的空格的行,但不會退出。它似乎處於一個無限循環中。它爲什麼不退出?

+0

它不會這樣做。它會正確執行。你正在使用哪個平臺。 – 2015-11-02 04:43:35

+2

您必須在行的開頭輸入Ctrl-D才能註冊爲EOF。請參閱http://unix.stackexchange.com/a/19097/7084 –

+0

我正在Linux Mint上的bash命令行中運行該程序。 –

回答

1

這是由於在POSIX標準中指定讀系統調用的方式。 http://pubs.opengroup.org/onlinepubs/9699919799/

當EOF被接收時,所有的等待要被讀取的字節是立即 傳遞給過程,而無需等待一個新行,和EOF是 丟棄。因此,如果沒有等待的字節(也就是說,EOF 發生在一行的開始處),則從read()返回的零的字節計數應爲 ,表示文件結束指示

getchar在I/O庫中是使用面向行的讀系統調用來實現的。這意味着read()一次向主叫方提供一條線路。 I/O庫將read()返回的字節存儲在緩衝區中,如果是getchar,則一次向進程傳送一個字節。

read()面向行的事實會導致Cntl-D的不同行爲,具體取決於輸入是否在行的開始位置。根據規格,一行開頭的Cntl-D立即發出EOF信號。

但是,行中間的Cntl-D的行爲不同。它將剩餘的字節發送到進程並丟棄EOF。這就是爲什麼需要另一個Cntl-D向該過程發信號通知EOF的原因。

+0

這就是我做錯了。輸入文本後我立即點擊cntl-d,因此程序丟棄了EOF。這是一個很大的幫助。謝謝ThomasG !!!!!!!! –

0

我似乎你正在使用的平臺上的CTRL-D不是正確的鍵綁定發送EOF。例如。在Windows上,通常是CTRL-Z。

編輯:是的,正如其他人已經指出,EOF需要在一行的開頭,所以你需要先發送一個換行符。

+0

我在Linux Mint上運行bash上的程序,所以它是ctrl-d,我剛剛在文本之後立即輸入它,而不是先輸入換行符。謝謝!!! –