EOF是什么?
我學習C語言的時候,遇到的一個問題就是 EOF。
它是 end of file 的縮寫,表示"文字流"(stream)的結尾。這里的"文字流",可以是文件(file),也可以是標準輸入(stdin)。
比如,下面這段代碼就表示,如果不是文件結尾,就把文件的內容復制到屏幕上。
int c;while ((c = fgetc (fp)) != EOF) { putchar (c); }</pre>
</blockquote>很自然地,我就以為,每個文件的結尾處,有一個叫做 EOF 的特殊字符,讀取到這個字符,操作系統就認為文件結束了。
但是,后來我發現,EOF 不是特殊字符,而是一個定義在頭文件 stdio.h 的常量,一般等于-1。
#define EOF (-1)
于是,我就困惑了。
如果 EOF 是一個特殊字符,那么假定每個文本文件的結尾都有一個 EOF(也就是-1),還是可以做到的,因為文本對應的 ASCII 碼都是正值,不可能有負值。但是,二進制文件怎么辦呢?怎么處理文件內部包含的-1呢?
這個問題讓我想了很久,后來查了資料才知道,在 Linux 系統之中,EOF 根本不是一個字符,而是當系統讀取到文件結尾,所返回的一個信號值(也就是-1)。至于系統怎么知道文件的結尾,資料上說是通過比較文件的長度。
所以,處理文件可以寫成下面這樣:
int c;while ((c = fgetc (fp)) != EOF) { do something }</pre>
</blockquote>這樣寫有一個問題。fgetc ()不僅是遇到文件結尾時返回 EOF,而且當發生錯誤時,也會返回 EOF。因此,C語言又提供了 feof ()函數,用來保證確實是到了文件結尾。上面的代碼 feof ()版本的寫法就是:
int c;while (!feof (fp)) { c = fgetc (fp); do something; }</pre>
</blockquote>
但是,這樣寫也有問題。fgetc ()讀取文件的最后一個字符以后,C語言的 feof ()函數依然返回0,表明沒有到達文件結尾;只有當 fgetc ()向后再讀取一個字符(即越過最后一個字符),feof ()才會返回一個非零值,表示到達文件結尾。
所以,按照上面這樣寫法,如果一個文件含有n個字符,那么 while 循環的內部操作會運行n+1次。所以,最保險的寫法是像下面這樣:
int c = fgetc (fp);while (c != EOF) { do something; c = fgetc (fp); } if (feof (fp)) { printf ("\n End of file reached."); } else { printf ("\n Something went wrong."); }</pre>
</blockquote>
除了表示文件結尾,EOF 還可以表示標準輸入的結尾。
int c;while ((c = getchar ()) != EOF) { putchar (c); }</pre>
</blockquote>
但是,標準輸入與文件不一樣,無法事先知道輸入的長度,必須手動輸入一個字符,表示到達 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,連續輸入兩次就行了。
來自: 阮一峰的網絡日志本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!