判斷檔案結束有兩種方法:eof和feof()
檢視stdio.h可以看到如下定義:
#define eof (-1)
#define _ioeof 0x0010
#define feof(_stream) ((_stream)->_flag & _ioeof)
由此可以看出,這兩種方式的原理是不同的。
有人說eof只能用於文字檔案,其實不然,還要看定義的變數的型別。下面這段程式對文字檔案和二進位制檔案都可以:
int c;
while((c=fgetc(fp)) != eof)
如果讀到了ff,由於c定義為int型,所以實際上c=0x000000ff,不等於eof(-1=0xffffffff),因此不會誤判為檔案結尾。 但是如果把c定義為char型別,就有可能產生混淆了。
char c;
while((c=fgetc(fp)) != eof)
因為文字檔案中儲存的是ascii碼,而ascii碼中ff代表空值(blank),一般不使用,所以如果讀檔案返回了ff,說明已經到了文字檔案的結尾。但是如果是二進位制檔案,其中可能會包含ff,因此不能把讀到eof作為檔案結束的條件,此時只能用feof()函式。
在vc裡,只有當檔案位置指標(fp->_ptr)到了檔案末尾,然後再發生讀/寫操作時,標誌位(fp->_flag)才會被置為含有_ioeof。然後再呼叫feof(),才會得到檔案結束的資訊。因此,如果執行如下程式:
char c;
while(!feof(fp))
會發現多輸出了乙個ff,原因就是在讀完最後乙個字元後,fp->flag仍然沒有被置為_ioeof,因而feof()仍然沒有探測到檔案結尾。直到再次呼叫fgetc()執行讀操作,feof()才能探測到檔案結尾。這樣就多輸出了乙個-1(即ff)。
正確的寫法應該是:
char c;
c = fgetc(fp);
while(!feof(fp))
注意這是正確的解法,譚浩強的書裡有乙個錯誤就是因為沒有注意到這個問題,下面請看
這個檔案複製程式**,紅色表示錯誤
錯解:注意紅色部分#include
#include
main()
if((out=fopen("out.txt","w"))==null)
while(!feof(in))
fclose(in);
fclose(out);}
看正確的**:
#include
#include
main()
if((out=fopen("out.txt","w"))==null)
ch=fgetc(in);
while(!feof(in))
/*while((ch=fgetc(in))!=eof)
fputc(ch,out);這個**也是正確的ch字元變數時只能應用於文字檔案,*/
fclose(in);
fclose(out);}
這麼說其實feof()是可以用eof來代替的嘍?不是,這裡還有乙個問題。fgetc返回-1時,有兩種情況:讀到檔案結尾或是讀取錯誤。因此我們無法確信檔案已經結束, 因為可能是讀取錯誤! 這時我們需要feof()。
你真的了解EOF和feof嗎?
判斷檔案結束有兩種方法 eof和feof 檢視stdio.h可以看到如下定義 define eof 1 define ioeof 0x0010 define feof stream stream flag ioeof 由此可以看出,這兩種方式的原理是不同的。有人說eof只能用於文字檔案,其實不然,還...
你真的了解Java嗎?
三目運算子規則 如果第二個和第三個運算元具有相同的型別,那麼它就是條件表示式的類 型。換句話說,你可以通過繞過混合型別的計算來避免 煩。如果乙個運算元的型別是 t,t 表示 byte short 或 char,而另乙個運算元是乙個 int 型別的常量表示式,它的值是可以用型別 t 表示的,那麼條件表...
你真的了解restful api嗎?
在以前,乙個 的完成總是 all in one 頁面,資料,渲染全部在服務端完成,這樣做的最大的弊端是後期維護,擴充套件極其痛苦,開發人員必須同時具備前後端知識。於是慢慢的後來興起了前後端分離的思想 後端負責資料編造,而前端則負責資料渲染,前端靜態頁面呼叫指定api獲取到有固定格式的資料,再將資料展...