feof 多讀一次的解決方法

2021-07-03 05:16:45 字數 1565 閱讀 8739

檢視 stdio.h 可以看到如下定義:

#define  eof  (-1)

#define  _ioeof  0x0010 

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

由此可以看出,這兩種方式的原理是不同的。

在這裡先說下eof和feof()這個兩個巨集定義,在我們學的課本中有這樣的描述。

eof是不可輸出字元,因此不能在螢幕上顯示。由於字元的ascii碼不可能出現-1,因此eof定義為-1是合適的。當讀入的字元值等於eof時,表示讀入的已不是正常的字元而是檔案結束符,但這適用對文字檔案的讀寫。在二進位制檔案中,資訊都是以數值方式存在的。eof的值可能就是所要處理的二進位制檔案中的資訊。這就出現了需要讀入有用資料卻被處理為「檔案結束「的情況。為了解決這個問題,c提供了乙個feof()函式,可以用它來判斷檔案是否結束。feof(fp)用於測試fp所指向的檔案的當前狀態是否為「檔案結束」。如果是,函式則返回的值是1(真),否則為0(假)。

說了這兩個的定義,肯定還對二進位制檔案和文字檔案的區別有些模糊那現在就回顧下這兩個檔案的概念。c語言支援的是流式檔案,它把檔案看作由乙個乙個的字元(位元組)資料組成的序列。根據資料的組織和操作形式,可以分為ascii檔案和二進位制檔案。

ascii檔案又稱為文字檔案,它是在乙個位元組的儲存單元上存放乙個字元(在外存中存放的是該字元的ascii碼,每個字元將佔乙個位元組)。

二進位制檔案是把記憶體中的資料按其在記憶體中的儲存格式在磁碟上原樣儲存。 

對字元而言,由於其外存儲存格式和記憶體表示格式相同,所以,在外存上也存放每個字元的ascii碼。

但是說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)) 

feof多讀一次問題分析

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

第一次使用git提交失敗的解決方法

在第一次練習使用時,在使用git commit命令時會執行失敗,比如我在首次使用時先使用git init命令初始化本地倉庫,然後要用git commit m initial commit 命令提交,但是提示失敗 please tell me who you are.run git config gl...

記錄一次伺服器被入侵的解決方法 轉

一 問題說明 1 我的伺服器是使用的阿里雲的centos,收到的阿里雲發來的提示郵件如下 所謂 挖礦 實質上是用計算機解決一項複雜的數學問題,來保證位元幣網路分布式記賬系統的一致性。位元幣網路會自動調整數學問題的難度,讓整個網路約每10分鐘得到乙個合格答案。隨後位元幣網路會新生成一定量的位元幣作為賞...