2014-01-12 97 views
0

我寫簡單的代碼在C中存儲的學生信息(卷號,姓名,課程,費用,部門)在一個文本文件student.txt - 代碼片段:C文件處理記錄搜索:最後一個記錄顯示兩次

FILE *fp; 
fp=fopen("student.txt","r"); 
//Input details from user and .. 
//store it in student.txt 
fprintf(fp,"%d %s %s %d %s ",s.rollno,s.name,s.course,s.fee,s.dept); 

我寫了下面的代碼來檢索和打印文件中的所有記錄,並檢索最後一個記錄TWICE!

while (!feof(fp)) 
      { 
       fscanf(fp,"%d%s%s%d%s",&s.rollno,s.name,s.course,&s.fee,s.dept); 

       printf("%d %s %s %d %s\n",s.rollno,s.name,s.course,s.fee,s.dept); 

      } 

//OUTPUT : 
46 mustafa be 12000 cse 
41 Sam BE 32000 CSE 
42 Howard BE 25000 EE 
44 Sheldon BE 25000 CSE 
44 Sheldon BE 25000 CSE 

爲什麼最後一個記錄(Sheldon ..)被從文件中讀取兩次(儘管它在文件中只寫了一次,我檢查過)。請幫助,真的卡住了。

回答

0

只有在您嘗試讀取超出文件末尾後,纔會設置流的EOF指示符。因此,除非您已經嘗試過分,否則feof()的測試將不起作用。

你可以看到在ISO C11標準的這種行爲它爲fgetc規定:如果流最終的文件指示設置

,或者如果流是在結束OF-文件,流的文件結束指示符被設置,並且fgetc函數返回EOF。

換句話說,第一次爲流設置EOF標誌是當您嘗試讀取文件中最後一個字符以外的第一個字符時。

你的情況發生了什麼是文件指針文件的末尾,剛剛成功讀取最後一個字符。它比fscanf()跳過前導空白等等的能力稍微複雜一點,但基本上,下一個fscanf()將在掃描任何項目之前讀取超出文件末尾的位置。

而且,當您的文件的末尾時,feof()尚未成立。然後您的代碼將嘗試fscanf,這將失敗(並設置EOF標誌),並且printf將再次輸出以前的內容(因爲fscanf沒有更改它們)。

由於fscanf成功返回掃描,你可能會選擇類似的項目數:

while (fscanf (fp, "%d%s%s%d%s", blah, blah) == 5) { 
    printf (blah, blah); 
} 
// check feof here to deside if EOF or bad input line. 

請參見下面的程序爲一個完整的例子:

#include <stdio.h> 

int main (void) { 
    int rollno, fee; 
    char name[100], course[100], dept[100]; 
    FILE *fp = fopen ("qq.in", "r"); 
    if (fp == NULL) { 
     puts ("Cannot open file"); 
     return 1; 
    } 
    while (fscanf (fp, "%d%s%s%d%s", &rollno, name, course, &fee, dept) == 5) { 
     printf ("%d %s %s %d %s\n", rollno, name, course, fee, dept); 
    } 
    fclose (fp); 
    return 0; 
} 
+0

哇!晶瑩剔透。 Thanx :) – Mustafa

+0

在這裏只有2個疑問,我可以繼續滿意: 1.當文件指針位於文件末尾時,爲什麼feof()不正確?從技術上講,應該是最後一個字符後面沒有空格。 2. fscanf()實際返回什麼?與使用的格式說明符的數量有關? – Mustafa

+0

@Mustafa:1 /因爲這就是標準所說的:-)當你試圖閱讀_too時,EOF是一個標記集。即使它被設置在文件結尾,這也不會有幫助,因爲fscanf可能會讓你處於最後的換行字符,不在文件結尾。掃描功能會跳過像'%d'這樣的主要空白。 2 /'fscanf'爲您提供成功轉換的項目數,因此5是理想的。 0意味着EOF或第一個東西不能用'%d'作爲數字解碼。 – paxdiablo