原文鏈接:http://blog.csdn.net/flyyyri/article/details/5084981
在c語言中經(jīng)常用EOF和feof()來判斷文件的結(jié)束,現(xiàn)將有關(guān)用法總結(jié)如下:
- 定義
EOF是End Of File 的縮寫,是c語言中標(biāo)準(zhǔn)庫中定義的宏,定義為:#define EOF (-1); feof() 用于測試流文件的結(jié)束,有宏和函數(shù)兩種定義: 宏定義: #define feof(_stream) ((_stream)->_flag & _IOEOF),其中_IOEOF的為:#define _IOEOF 0x0010 函數(shù)定義:int feof( FILE *stream ); - 說明
EOF的值為-1,是int類型數(shù)據(jù),在32位系統(tǒng)中,可以表示為0xFFFFFFFF; EOF 不是一個字符,也不是文件中實際存在的內(nèi)容。EOF不但能表示讀文件到了結(jié)尾這一狀態(tài),它還能表示 I/O 操作中的讀、寫錯誤(可以用 ferror() 來檢測)以及其它一些關(guān)聯(lián)操作的錯誤狀態(tài); feof()只用于測試流文件的結(jié)束,當(dāng)?shù)竭_(dá)結(jié)尾時,返回非0;當(dāng)文件內(nèi)部位置指針指向文件結(jié)束時,并未立即置位FILE結(jié)構(gòu)中的文件結(jié)束標(biāo)記,只有再執(zhí)行一次讀文件操作,才會置位結(jié)束標(biāo)志,此后調(diào)用feof才會返回為真。 函數(shù)如fgetc或getc返回EOF并不一定表示文件結(jié)束,當(dāng)讀取文件出錯時也會返回EOF,僅憑返回-1就認(rèn)為文件結(jié)束是錯誤的;正因為如此,我們需要feof()來判斷文件是否結(jié)束,當(dāng)然用feof()來判斷文件結(jié)束時也需要判斷讀取操作是否出錯,這時可以用ferror()來判斷,當(dāng)其為真時表示有錯誤發(fā)生。在實際的程序中,應(yīng)該每執(zhí)行一次文件操作,就用用ferror函數(shù)檢測是否出錯。 - 舉例
假設(shè)文件指針fp指向某個文件,文件中有字符串“hello”,下面的代碼將輸出hello外,還將輸出一個結(jié)束字符EOF(EOF是fgetc函數(shù)的返回值,并不是文件中存在EOF):
- int c=0;
- while(!feof(fp))
- {
- int c=fgetc(fp);
- printf('%c:/t%x/n',c,c);
- }
其原因就是當(dāng)內(nèi)部指針指向結(jié)尾時,還要執(zhí)行一次讀操作,文件結(jié)束標(biāo)記才置位,而下面的代碼將只輸出“hello”不輸出文件結(jié)束符:
- int c;
- c=fgetc(fp);
- while(!feof(fp))
- {
- printf('%c:/t%x/n',c,c);
- c=fgetc(fp);
- }
當(dāng)文件內(nèi)部指針指向結(jié)束位置時,先執(zhí)行一次讀操作,置位文件結(jié)束標(biāo)記,while循環(huán)立即結(jié)束。 - 需要注意的幾點
(1) 字節(jié)的讀取和寫入 fgetc或getc返回一個int類型數(shù)據(jù),在正常的情況下, fgetc或getc以 unsigned char 的方式讀取文件流, 擴(kuò)張為一個整數(shù),并返回. 換言之, fgetc 從文件流中取一個字節(jié), 并加上24個零,成為一個小于256的整數(shù),然后返回。
- int c;
- while ((c = fgetc (rfp))!= -1) // -1就是 EOF
- fputc (c, wfp);
在正常讀取的情況下, 上述fgetc函數(shù)返回的整數(shù)均小于256, 即0x0~0xFF. 而讀不出 0xFFFFFFFF;而寫入時fputc 中的 c 雖然是整數(shù), 但在 fputc 將其寫入文件流之前, 又把整數(shù)的高24位去掉了, 所以如果用fputc把 0xFFFFFFFF 往文件里頭寫, 高24位被屏蔽,寫入的將是 0xFF. (2) fgetc返回值的類型(以(1)中的代碼為例) fgetc()返回類型為int,我們可以將其返回值賦給一個int類型變量,如(1)中的代碼,即使是遇到字符0xFF(blank的ascii碼,不是EOF),while循環(huán)也不會結(jié)束,因為0xFF會被轉(zhuǎn)化0x000000FF,顯然這與0xFFFFFFFF(EOF)是不相等的,這時能完成正確復(fù)制; 如果用一個char 類型的變量c 來接收fgetc()的返回值,會出現(xiàn)什么情況? 假定下一個讀取的字符為0xFF 則: char c = fgetc (rfp); // fgetc(rfp)的值為 0x000000FF, 然后強制轉(zhuǎn)化為char類型:c = 0xFF while(c != EOF) ; // 字符與整數(shù)比較? c 被帶符號(signed)擴(kuò)展為0xFFFFFFFF,條件成立,文件復(fù)制提前退出,故遇到空格字符時就退出,不能完成復(fù)制; 如果將c 定義為unsigned char,當(dāng)讀到文件末尾,返回 EOF 也就是 -1 時: unsigned char c = fgetc (rfp);// fgetc (rfp)的值為EOF,即-1,即0xFFFFFFFF,然后強制轉(zhuǎn)化為uchar類型, c=0xFF while( c!= -1) ; // c 被擴(kuò)展為 0x000000FF, 永遠(yuǎn)不會等于 0xFFFFFFFF,所以這次雖然能正確復(fù)制 0xFF, 但卻不能判斷文件結(jié)束. 事實上,在 c 為 uchar 時,c != -1 是永遠(yuǎn)成立的! 因此,只能將c定義成int類型的變量,這樣才與fgetc返回類型一致。
|