C> fgets讀取文件最后一行重復問題


1.fgets描述
linux下man fgets查手冊知道,fgets()會一直讀到文件EOF或者一個新行。換行符("\n")會放入fgets指定緩沖區,且末尾后會加入"\0";
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read , it is stored into buffer. A terminating null byte ("\0") is store after the last character in the buffer.

 

2.fgets, gets區別

gets()和fgets()都是可以從鍵盤輸入字符串,遇到換行符或EOF為止。那么它們有什么區別呢?
1)gets()沒有指定輸入字符大小,會無限讀取。但是不安全,要求程序員自行控制緩沖區大小;fgets()會要求指定輸入字符大小,不會無限讀取,更安全。
 
e.g. 假設輸入的字符串長度 > s緩存長度,也不會報錯,但是可能會溢出。溢出不一定會報錯,要看溢出的RAM空間是否會影響到別的進程。
char s[2];
gets(s);
printf("%s", s);

 

e.g. 輸入字符串長度不能超過指定讀取的長度,而且最后一個byte會用於填充'\0'(fgets指定size的最后1個byte,而非緩存中最后1個byte才填充 '\0')。 如果超過,超過的內容會留在輸入流中。
char s[2];
fget(s, sizeof(s), stdin);
printf("%s", s);

 

3.fgets最后一行重復問題
當最后一行為空時,fgets會重復倒數第二行數據。
 
e.g. fgets讀取ASCII文本。 
 1 void read_file1()
 2 {
 3     FILE *fp ;
 4     char *fileName = "./test.txt"; //待讀取文本文件
 5  
 6     if((fp = fopen(fileName, "r")) == NULL)
 7     {
 8         printf("file %s does not exist.\n", fileName);
 9         return -1;
10     }
11  
12     char s[256] = {0};
13     int lineNum = 0;
14  
15     while(!feof(fp))
16     {
17         fgets(s, sizeof(s), fp);
18  
19         printf("%d: %s\n", lineNum, s);
20         printf("len = %d\n", strlen(s));
21         printf("last char's ASCII code = %d\n", s[strlen(s) - 1]);
22  
23         lineNum ++;
24     }
25  
26     fclose(fp);
27 }
 
當文本文件內容為下面內容時,打印正常
aaa
bbb
打印結果:
 
檔文本內容為下面內容時(相比較上面,多出一個空行,即最后一行是空),打印則不正常,輸出最后一行不是空,也不是忽略了,而是重復了倒數第二行內容。這是為什么呢?
aaa
bbb

 

打印結果:
 
分析:
首先是循環結束條件,feof(fp)是檢測流上的文件結束符,如果文件結束,則返回非0;如果文件未結束,則返回0。
第1行"bbb\n"讀完以后,此時並不知道文件結尾,s="bbb\n\0",會繼續讀下一行。
第2行""(空)會讀到文件結尾EOF,正常情況會將'\0'用於填入空串后,為何還會填充前面一行內容呢?
這是因為用fgets獲取最后一行(空行)失敗,而抓取的s數據會在檢查到已經到文件結尾(循環結束條件)之前,就打印了。也就是說打印內容其實是無效的,實際上fgets並未影響到緩存s內容,也就是倒數第二行內容。
 
改善:將打印數據內容放到檢查是否已經碰到文件末尾之后
FILE *fp;
char s[256];
while(true)
{
    fgets(s, sizeof(s), fp);
    if(feof(fp))
    {
        break;
    }
    
    printf("%s", s);
}
 
fclose(fp);

 

打印結果:
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM