張吳波,史旅華(湖北汽車工業(yè)學(xué)院電子信息工程學(xué)院,十堰 442002)
C語言程序中如何正確使用feof函數(shù)
張吳波,史旅華
(湖北汽車工業(yè)學(xué)院電子信息工程學(xué)院,十堰 442002)
文件是存儲在外部介質(zhì) (如磁盤)上的數(shù)據(jù)的集合,這些數(shù)據(jù)能長期保留,可以隨時存取。在C語言程序設(shè)計中經(jīng)常需要將處理的數(shù)據(jù)保存在文件中,并從文件中讀取數(shù)據(jù)。C語言提供了許多的標(biāo)準(zhǔn)函數(shù)進行文件的操作,在筆者多年的《C語言程序設(shè)計》講授中,發(fā)現(xiàn)學(xué)生對文件的操作不熟悉,讀寫文件經(jīng)常出錯,從文件中讀取數(shù)據(jù)時尤為突出。
C語言中對文件進行讀取操作時,先打開文件。C語言提供了fopen()函數(shù)來打開文件,其返回值是一個FILE類型的文件指針。然后再通過C語言提供的文件讀取函數(shù),例如fgetc()、fgets()、fscanf()、fread()等函數(shù),從文件中將數(shù)據(jù)讀取到程序的內(nèi)存空間。
理解文件讀取函數(shù)是如何從文件中讀取數(shù)據(jù),對正確地從文件中讀取數(shù)據(jù)非常重要。由于磁盤是慢速設(shè)備,如果每向磁盤寫入一個字節(jié)或讀出一個字節(jié)的數(shù)據(jù),都要啟動磁盤操作,將會大大降低系統(tǒng)的效率,而且還會對磁盤驅(qū)動器的使用壽命帶來不利影響。因此,在文件系統(tǒng)中往往使用緩沖技術(shù),即系統(tǒng)在內(nèi)存中為每個正在使用的文件開辟一個緩沖區(qū),利用緩沖區(qū)完成文件讀寫操作。打開文件是在文件與程序之間建立起聯(lián)系,程序把所要操作的文件的有關(guān)信息,如文件名、文件操作方式等通知給系統(tǒng);系統(tǒng)根據(jù)文件的有關(guān)信息為該文件分配相應(yīng)的文件緩沖區(qū)[1]。
FILE是在stdio.h中定義的結(jié)構(gòu)體類型,它包含了與文件操作有關(guān)的信息,如文件對應(yīng)的內(nèi)存緩沖區(qū)地址、讀寫位置、操作方式、文件結(jié)束標(biāo)志等。當(dāng)打開一個文件時,系統(tǒng)自動為每個文件開辟一個“文件信息區(qū)”,用于存放上述信息。C程序用不同的FILE結(jié)構(gòu)管理每個文件。在VC 6.0中,F(xiàn)ILE結(jié)構(gòu)體的定義如下:
其中成員base表示文件緩沖區(qū)的起始位置,成員_ptr是文件位置指針,指示文件當(dāng)前的讀寫位置。從文件中讀取數(shù)據(jù)后,它就向后移動相應(yīng)的字節(jié)。_flag表示文件當(dāng)前的狀態(tài),其中的不同二進制位代表文件中不同的狀態(tài),例如文件是否結(jié)束、文件讀取是否出錯等[2]。
由于文件中可能存放多個數(shù)據(jù),因此在使用這些函數(shù)從文件讀取數(shù)據(jù)時,一般都使用循環(huán)的方式。那么在循環(huán)中如何確定文件讀取已經(jīng)結(jié)束呢?C語言提供了feof()函數(shù),用于判斷文件是否結(jié)束:如果文件讀取結(jié)束,函數(shù)返回1(真),否則返回0(假)。因此在讀取文件時,經(jīng)常使用該函數(shù)判斷[3]。
但是廣大C語言初學(xué)者經(jīng)常會碰到如下的情況,而對編寫讀取文件的程序產(chǎn)生困惑。例如:程序pro1.c讀取該文件的內(nèi)容,并顯示在屏幕上。
在文件data.txt的內(nèi)容為ABCDEFGH和內(nèi)容為ABCDEFG時,程序運行結(jié)果截然不同,如圖1所示。
圖1 pro1.c程序運行結(jié)果
從上面的運行結(jié)果發(fā)現(xiàn),在第一種情況下,程序多輸出了一次。為什么會這樣呢,這是由于feof()函數(shù)給出返回值的規(guī)則造成的。在VC 6.0中,feof()函數(shù)根據(jù)文件結(jié)束標(biāo)志返回結(jié)果,如果文件結(jié)束標(biāo)志被置為1,則返回1,否則返回0。那么文件結(jié)束標(biāo)志什么時候被置為1呢?在讀取文件時,即使文件位置指針 (fp->_ptr)指向了文件末尾(雖然文件中的數(shù)據(jù)都已經(jīng)被讀出),文件結(jié)束標(biāo)志仍為0,只有再發(fā)生讀操作,它才被置為1[4]。
上述的pro1.c程序中,當(dāng)data.txt文件中的數(shù)據(jù)為ABCDEFGH時,文件結(jié)束標(biāo)志的變化過程如圖2所示。
圖2 _ptr指針移動與文件結(jié)束標(biāo)志變化
從上面的示意圖可以看出,當(dāng)?shù)诙巫x取時,fgets()恰好從文件讀取4個字符,而文件位置指針_ptr雖然已經(jīng)指向了文件末尾,因為此時不再從文件中讀取數(shù)據(jù),文件結(jié)束標(biāo)志仍然為0,所以feof()函數(shù)返回值為0。因此程序會執(zhí)行第三次循環(huán),再調(diào)用fgets()函數(shù)從文件中讀取數(shù)據(jù)時,系統(tǒng)才將文件結(jié)束標(biāo)志置為1,并改變_ptr指向,再使用feof函數(shù)判斷時,函數(shù)返回1。
從上面的分析可以看出,使用feof()函數(shù)判斷文件是否結(jié)束時,可能會發(fā)生這樣的情況:實際文件中的最后一個數(shù)據(jù)已經(jīng)讀取完畢,但feof()函數(shù)仍返回0,如果根據(jù)feof()函數(shù)的返回值判斷,此時會導(dǎo)致多讀一次文件而產(chǎn)生錯誤的結(jié)果。那么如何正確使用feof()函數(shù),以避免產(chǎn)生錯誤呢?這個錯誤產(chǎn)生的根本原因是因為feof()函數(shù)使用的時機不對,一般的使用方法可以按照圖3所表示的流程使用。
上面的方法對于使用fgetc()函數(shù)、fscanf()函數(shù)、fread()函數(shù)可以正確地進行文件的讀取。但是對于fgets()函數(shù),由于最后一次從文件中讀取的字符個數(shù)可能會比參數(shù)指定的讀取字符個數(shù)少,而此時文件結(jié)束標(biāo)志會置為1。按照按照上面的流程,則會漏掉對最后讀取數(shù)據(jù)的處理。在這種情況下,如果使用feof()函數(shù)作為循環(huán)的結(jié)束條件時,須結(jié)合文件讀取函數(shù)的返回值進行判斷。
圖3 使用feof函數(shù)一般的流程
將pro1.c程序修改如下:
或者修改如下:
上面修改后的程序,當(dāng) data.txt中的內(nèi)容為ABCDEFGH或者為ABCDEFG時,都能正確地讀取、顯示文件中的數(shù)據(jù)。其中第二個修改的程序是在循環(huán)體中結(jié)合fgets()函數(shù)的返回值,判斷循環(huán)是否結(jié)束。
在《C語言程序設(shè)計》中,從文件中讀取數(shù)據(jù)是一個重點和難點。很多學(xué)生在使用文件編程時,經(jīng)常出現(xiàn)錯誤。尤其是循環(huán)讀取數(shù)據(jù)時,使用feof()函數(shù)判斷文件讀取是否結(jié)束,更為突出。究其原因是因為學(xué)生對C語言中文件讀寫機制不熟悉,對feof()函數(shù)返回結(jié)果的規(guī)則不了解。而這些知識點在許多教材和參考書中又很少提及,因此導(dǎo)致學(xué)生在具體應(yīng)用時出現(xiàn)了錯誤。
本文分析了feof()函數(shù)的工作機制和文件結(jié)束標(biāo)志在文件讀取過程中的修改過程。然后結(jié)合二者,提出了正確使用feof()函數(shù)的方法。可以幫助學(xué)生加深對文件讀取的理解,掌握對文件讀取操作的正確方法。
[1]史旅華,張吳波.C語言程序設(shè)計教程[M].人民郵電出版社,2014.8
[2]黃瑛.C語言教材中對feof函數(shù)的常見誤解與誤用[J].科技文匯,2012.5
[3]王銳.C語言存取文本文件技術(shù)探索[J].科技創(chuàng)新淪壇[J],2010.24
[4]林智勇.C語言案例教學(xué)之文件讀寫[J].現(xiàn)代計算機,2014.6
C Programming;File;FILE Struct;feof Function
How to Use the feof Function Correctly in C Language
ZHANG Wu-bo,SHI Lv-hua
(School of Electrical&Information Engineering,Hubei University of Automotive Techonlogy,Shiyan 442002)
1007-1423(2015)10-0053-04
10.3969/j.issn.1007-1423.2015.10.015
張吳波(1977-),男,湖南邵陽人,講師,研究方向為軟件開發(fā)
2015-02-26
2015-03-12
針對在C語言課程中學(xué)生從文件中讀取數(shù)據(jù)時經(jīng)常出錯的現(xiàn)象,分析FILE結(jié)構(gòu)體的意義和從文件中讀取數(shù)據(jù)的工作機制。然后結(jié)合具體程序,指出在應(yīng)用feof函數(shù)判斷文件結(jié)束時的錯誤,并分析feof函數(shù)的工作機制,提出一種正確使用feof函數(shù)進行文件讀取的方法。
C語言程序設(shè)計;文件;FILE結(jié)構(gòu)體;feof函數(shù)
史旅華(1963-),男,浙江寧波人,副教授,研究方向為圖形圖像處理研究
Focuses on the phenomenon that problem has happened when students read data from file using C language.Analyzes the importance of the FILE struct,and analyzes the process of reading data from file in C.According to some specific examples,points out the mistakes of using feof function to judge the end of reading data.Points out the process of judging end of file with feof function.At last proposes a way that how to correctly use the feof function to read data from file.