每當用C語言讀取文件內容時,文件指針要指向字符EOF之后才能判斷文件已經結束。所以EOF內容會被讀取,讀取到的EOF通常會給我們帶來困擾,如輸出時會多輸出一行。
為了解決多讀取的EOF字符(在文件中不可見),我們用一個小小的邏輯算法來避免EOF字符帶來的困惑,如打印讀取的文件內容時不將讀取到的EOF字符輸出,或避免在讀取到EOF字符(讀取此字符不成功)后無判斷文件是否結束的操作而又將上一次讀取到的數據輸出。
一、EOF (END OF FILE)是指文件的結束符,是一個宏定義。對於getchar(), 一般會返回一個我們鍵入的符號值。只有當遇到文本結束標記(ASC||碼值==26)才會返回EOF。
假如有“data.txt"文件內容:
123456
456789
那么用指針打開此文件,指針的移動過程如下:
1.打開文件時,FILE指針指向文件里的第一個字符,比如打開"data.txt",指針會指向'1'。
2.每根據需要(讀一個字符,一行字符串等 ) 讀取一次文件內容時,文件指針將指向下一個(臨近)的字符。
比如"data.txt"中的內容,用fgets(ar,50,fp);語句讀取了一行字符串后,fp將指向'4'。// fgets可以從文件中讀取一行字符串,存進先前定義的char數組里(如ar[50])。注意fget的格式。
3.當文件指針指向EOF時,並不會認為文件內容已經結束。當指針指向EOF后一位時(把EOF讀取后),此時文件內容才算結束。
如在data.txt中,把字符'9'成功讀取后,文件指針指向EOF字符。此時若判斷文件是否結束,則不為結束;只有把EOF字符讀取之后(文件指針指向EOF后時),再判斷文件是否結束時,才會判斷為結束。
二、feof()
能正確將文件內容輸出的關鍵語句是 "if( feof(fp) ){break;}" 需要將此語句加在"行數自增,打印行內容(ln++;printf("%s", ar))"語句之前。見一個例子
1 while( !feof(fp) ){ 2 fgets(ar, SIZE, fp); //fgets()函數自帶回車符 // fgets可以從文件中讀取一行字符串,存進先前定義的char數組里(如ar[50])。注意fget的格式。 3 4 //If read EOF, 5 //Do not record the line`s number, 6 //Do not print the content to screen 7 if( feof(fp) ){ 8 break; 9 } 10 ln++; 11 printf("%s", ar); 12 }
假如把" if( feof(fp) ) {break;}" 放在printf語句后面,最后一行字符”456789“ 就會被打印兩次,最終輸出的行數則+1.
造成這種結果的原因在於:讀取EOF字符時,FILE指針已經指向了EOF的后面,但這時沒有判斷 文件內容的讀取 是否已結束,從而沒有終止while循環,使fgets()函數讀取EOF字符失敗(不能說字符EOF被讀入到數組ar中),因此ar數組里還是上一次讀取的內容。所以會有這樣的輸出。
總結來說,feof(fp) 就是判斷fp是否已經讀取了EOF字符。如果已讀取,返回true值,while將break。
主要筆記來源: https://blog.csdn.net/misskissc/article/details/8219979
P.S. 此外,EOF還可用於循環判斷條件,如while(scanf("%d",&x)!=EOF) [等同於while(cin>>x)]
