feof多讀一次問題分析

2021-06-27 09:48:03 字數 2734 閱讀 3797

在讀完檔案的最後乙個字元後,fp->flag仍然沒有被置為_ioeof,因而feof()仍然沒有探測到檔案結尾。直到再次呼叫fgetc()執行讀操作,feof()才能探測到檔案結尾。這樣就多執行了一次。對於feof()這個函式, 它是先讀再判斷是否到檔案尾, 也就是說在它之前一定要讀一次才能做出判斷。

而我們經常這樣把它使用在迴圈中:

int c;

while(!feof(fp))

它是先判斷==>再讀(可能這時就是檔案尾了, 讀不出東西了)

所以正確的**應該是

int c;

c = fgetc(fp);//先讀一次  

while(!feof(fp))

看出上面兩段**的區別了吧!!!

第二種方法就是:(不使用feof,換種方法。)

1、把檔案內部指標移動到檔案尾部。

fseek(fp,0,2);

2、用乙個整形變數記錄這個檔案尾部的位置

wjcd = ftell(fp);

3、把檔案內部指標移到到檔案頭部;

fseek(fp,0,0);

4、這樣就可以了

while(wjcd == ftell(fp))

注: 1)   欲將讀寫位置移動到檔案開頭時:fseek(file   *stream,0,seek_set);

2)   欲將讀寫位置移動到檔案尾時:fseek(file   *stream,0,seek_end);

引數seek_set是從距檔案開頭offset位移量為新的讀寫位置;seek_cur是以目前的讀寫位置往後增加offset個位移量;seek_end將讀寫位置指向檔案尾後再增加offset個位移量。當whence值為seek_cur或seek_end時,引數offset允許負值的出現。

當feof(file *)讀到eof標誌並不認為檔案結束了,依舊返回0,直到讀到eof的下乙個字元才返回1,這時才認為是檔案結束。

因此若以while(!feof(fp))為迴圈條件的時候,要將乙個檔案(fp)完全複製到另乙個檔案(fp1),需要加上判斷if(ch!=-1),如下:

while(!feof(in))

或者:while(true)

檢測流上的檔案結束符

the function feof() tests the end-of-file indicator for the stream

pointed to by stream, returning non-zero if it is set. the end-of-file

indicator can only be cleared by the functionclearerr().

如果檔案結束,則返回非0值,否則返回0,檔案結束符只能被clearerr()清除。

eof是文字檔案結束的標誌。在文字檔案中,資料是以字元的ascⅱ**值的形式存放,普通字元的ascⅱ**的範圍是32到127(十進位制),eof的16進製制**為0xff(十進位制為-1),因此可以用eof作為檔案結束標誌。[1]

當把資料以二進位制形式存放到檔案中時,就會有-1值的出現,因此不能採用eof作為二進位制檔案的結束標誌。為解決這乙個問題,asci c提供乙個feof函式,用來判斷檔案是否結束。feof函式既可用以判斷二進位制檔案又可用以判斷文字檔案。

「c」語言的「feof()」函式和資料庫中「eof()」函式的運作是完全不同的。資料庫中「eof()」函式讀取當前指標的位置,「c」語言的「feof()」函式返回的是最後一次「讀操作的內容」。多年來把「位置和內容」相混,從而造成了對這一概念的似是而非。

那麼,位置和內容到底有何不同呢?舉個簡單的例子,比如有人說「你走到火車的最後一節車箱」這就是位置。而如果說「請你一直向後走,摸到鐵軌結束」這就是內容。也就是說用內容來判斷會「多走一節」。這就是完全依賴於「while(!feof(fp))」進行檔案複製時,目標文件總會比源文件「多出一些」的原因。

在「c」檔案讀取操作時不能完全依賴於「while(!feof(fp))」的判斷。下面**是改進後的**,該**執行後output檔案內容和input檔案內容一致,與使用「while(!feof(fp))」相比,output檔案的結尾符號(eof)沒有被讀入到input檔案中。

linux 下編譯通過、vc下也行。

#include

#include

int main(void)

if((out=fopen("./input.txt","w"))==null)

while(1)

fclose(in);

fclose(out);

return 0;

}與eof的區別

在stdio.h中可以看到如下定義:

#define eof (-1)

#define _ioeof 0x0010

#define feof(_stream) ((_stream)->_flag & _ioeof)

int c;

while(!feof(fp))

會發現多輸出了乙個ff,原因就是在讀完最後乙個字元後,fp->flag仍然沒有被置為_ioeof,因而feof()仍然沒有探測到檔案結尾。直到再次呼叫fgetc()執行讀操作,feof()才能探測到檔案結尾。這樣就多輸出了乙個-1(即ff)。

正確的寫法應該是:

int c;

c = fgetc(fp);

while(!feof(fp))

feof()可以用eof代替嗎?不可以。fgetc返回-1時,有兩種情況:讀到檔案結尾或是讀取錯誤。因此我們無法確信檔案已經結束, 因為可能是讀取錯誤! 這時我們需要feof()。

feof 多讀一次的解決方法

檢視 stdio.h 可以看到如下定義 define eof 1 define ioeof 0x0010 define feof stream stream flag ioeof 由此可以看出,這兩種方式的原理是不同的。在這裡先說下eof和feof 這個兩個巨集定義,在我們學的課本中有這樣的描述。e...

用feof 判斷檔案時出現多讀內容的問題

昨天將自己以前做的電子通訊錄加上了檔案讀寫的功能,是的資料可以關機儲存,開機讀取。在修改的過程中出現了乙個問題就是每次開啟程式時,讀檔案內的內容總是會在最後多讀一串資料,經過上網查詢找到了問題所在。下面我先把我原來寫的錯誤的程式部分貼出 while 0 feof stream 這裡我是先用feof ...

c 讀檔案(一次全讀 每行讀 多次讀)

我以為這些都很容易在網上找到,誰知網上亂七八糟的東西太多,讓我找了很久。開發環境為windows,vs2013 一次全讀 std ifstream t path 讀檔案ifstream,寫檔案ofstream,可讀可寫fstream std stringstream buffer buffer t....