我學習C語言的時候,遇到的一個問題就是EOF。它是endoffile的縮寫,表示"文字流"(stream)的結尾。這裡的"文字流",可以是檔案(file),也可以是標準輸入(stdin)。比如,下面這段程式碼就表示,如果不是檔案結尾,就把檔案的內容複製到螢幕上。intc;
while((c=fgetc(fp))!=EOF){putchar(c);}很自然地,我就以為,每個檔案的結尾處,有一個叫做EOF的特殊字元,讀取到這個字元,作業系統就認為檔案結束了。但是,後來我發現,EOF不是特殊字元,而是一個定義在標頭檔案stdio.h的常量,一般等於-1。#defineEOF(-1)於是,我就困惑了。如果EOF是一個特殊字元,那麼假定每個文字檔案的結尾都有一個EOF(也就是-1),還是可以做到的,因為文字對應的ASCII碼都是正值,不可能有負值。但是,二進位制檔案怎麼辦呢?怎麼處理檔案內部包含的-1呢?這個問題讓我想了很久,後來查了資料才知道,在Linux系統之中,EOF根本不是一個字元,而是當系統讀取到檔案結尾,所返回的一個訊號值(也就是-1)。至於系統怎麼知道檔案的結尾,資料上說是透過比較檔案的長度。所以,處理檔案可以寫成下面這樣:intc;while((c=fgetc(fp))!=EOF){dosomething}這樣寫有一個問題。fgetc()不僅是遇到檔案結尾時返回EOF,而且當發生錯誤時,也會返回EOF。因此,C語言又提供了feof()函式,用來保證確實是到了檔案結尾。上面的程式碼feof()版本的寫法就是:intc;while(!feof(fp)){c=fgetc(fp);dosomething;}但是,這樣寫也有問題。fgetc()讀取檔案的最後一個字元以後,C語言的feof()函式依然返回0,表明沒有到達檔案結尾;只有當fgetc()向後再讀取一個字元(即越過最後一個字元),feof()才會返回一個非零值,表示到達檔案結尾。所以,按照上面這樣寫法,如果一個檔案含有n個字元,那麼while迴圈的內部操作會執行n+1次。所以,最保險的寫法是像下面這樣:intc=fgetc(fp);while(c!=EOF){dosomething;
c=fgetc(fp);}if(feof(fp)){printf("\nEndoffilereached.");}else{printf("\nSomethingwentwrong.");}除了表示檔案結尾,EOF還可以表示標準輸入的結尾。intc;while((c=getchar())!=EOF){putchar(c);}但是,標準輸入與檔案不一樣,無法事先知道輸入的長度,必須手動輸入一個字元,表示到達EOF。Linux中,在新的一行的開頭,按下Ctrl-D,就代表EOF(如果在一行的中間按下Ctrl-D,則表示輸出"標準輸入"的快取區,所以這時必須按兩次Ctrl-D);Windows中,Ctrl-Z表示EOF。(順便提一句,Linux中按下Ctrl-Z,表示將該程序中斷,在後臺掛起,用fg命令可以重新切回到前臺;按下Ctrl-C表示終止該程序。)那麼,如果真的想輸入Ctrl-D怎麼辦?這時必須先按下Ctrl-V,然後就可以輸入Ctrl-D,系統就不會認為這是EOF訊號。Ctrl-V表示按"字面含義"解讀下一個輸入,要是想按"字面含義"輸入Ctrl-V,連續輸入兩次就行了。(完)
我學習C語言的時候,遇到的一個問題就是EOF。它是endoffile的縮寫,表示"文字流"(stream)的結尾。這裡的"文字流",可以是檔案(file),也可以是標準輸入(stdin)。比如,下面這段程式碼就表示,如果不是檔案結尾,就把檔案的內容複製到螢幕上。intc;
while((c=fgetc(fp))!=EOF){putchar(c);}很自然地,我就以為,每個檔案的結尾處,有一個叫做EOF的特殊字元,讀取到這個字元,作業系統就認為檔案結束了。但是,後來我發現,EOF不是特殊字元,而是一個定義在標頭檔案stdio.h的常量,一般等於-1。#defineEOF(-1)於是,我就困惑了。如果EOF是一個特殊字元,那麼假定每個文字檔案的結尾都有一個EOF(也就是-1),還是可以做到的,因為文字對應的ASCII碼都是正值,不可能有負值。但是,二進位制檔案怎麼辦呢?怎麼處理檔案內部包含的-1呢?這個問題讓我想了很久,後來查了資料才知道,在Linux系統之中,EOF根本不是一個字元,而是當系統讀取到檔案結尾,所返回的一個訊號值(也就是-1)。至於系統怎麼知道檔案的結尾,資料上說是透過比較檔案的長度。所以,處理檔案可以寫成下面這樣:intc;while((c=fgetc(fp))!=EOF){dosomething}這樣寫有一個問題。fgetc()不僅是遇到檔案結尾時返回EOF,而且當發生錯誤時,也會返回EOF。因此,C語言又提供了feof()函式,用來保證確實是到了檔案結尾。上面的程式碼feof()版本的寫法就是:intc;while(!feof(fp)){c=fgetc(fp);dosomething;}但是,這樣寫也有問題。fgetc()讀取檔案的最後一個字元以後,C語言的feof()函式依然返回0,表明沒有到達檔案結尾;只有當fgetc()向後再讀取一個字元(即越過最後一個字元),feof()才會返回一個非零值,表示到達檔案結尾。所以,按照上面這樣寫法,如果一個檔案含有n個字元,那麼while迴圈的內部操作會執行n+1次。所以,最保險的寫法是像下面這樣:intc=fgetc(fp);while(c!=EOF){dosomething;
c=fgetc(fp);}if(feof(fp)){printf("\nEndoffilereached.");}else{printf("\nSomethingwentwrong.");}除了表示檔案結尾,EOF還可以表示標準輸入的結尾。intc;while((c=getchar())!=EOF){putchar(c);}但是,標準輸入與檔案不一樣,無法事先知道輸入的長度,必須手動輸入一個字元,表示到達EOF。Linux中,在新的一行的開頭,按下Ctrl-D,就代表EOF(如果在一行的中間按下Ctrl-D,則表示輸出"標準輸入"的快取區,所以這時必須按兩次Ctrl-D);Windows中,Ctrl-Z表示EOF。(順便提一句,Linux中按下Ctrl-Z,表示將該程序中斷,在後臺掛起,用fg命令可以重新切回到前臺;按下Ctrl-C表示終止該程序。)那麼,如果真的想輸入Ctrl-D怎麼辦?這時必須先按下Ctrl-V,然後就可以輸入Ctrl-D,系統就不會認為這是EOF訊號。Ctrl-V表示按"字面含義"解讀下一個輸入,要是想按"字面含義"輸入Ctrl-V,連續輸入兩次就行了。(完)