2014-03-06 44 views
0

誰能告訴我在這個程序中的漏洞......?其實它是兩次打印最後一個記錄。棟篤神探缺陷

#include <stdio.h> 

int main(void) 
{ 
    int accountNum; 
    char name[30]; 
    double balance; 
    int counter = 0; 

    FILE *clientDataFile1; 

    if((clientDataFile1 = fopen("clients.txt", "r")) == NULL) 
    printf("File could not be opened"); 
    else 
    { 
    printf("%-10s %-13s %s\n", "Account", "Name", "Balance"); 

    while(!feof(clientDataFile1)) 
    { 
     fscanf(clientDataFile1, "%d%s%lf", &accountNum, name, &balance);  
     printf("%-10d%-13s%.2lf\n", accountNum, name, balance); 
    } 

    printf("\n\n\n"); 
    rewind(clientDataFile1);  
    counter++; 
    fclose(clientDataFile1); 
    } 

    return 0; 
} 

這是變得非常painful.I嘗試了很多次,但缺陷是抓不到。要麼我的工作不清楚,要麼Ubuntu 12.10或gcc對此負責。 幫我......

+2

爲什麼你倒帶只是爲了關閉它?文件不是VHS磁帶。 – Kevin

+0

輕微:建議'「%d%29s%lf」'以防止'name'溢出。 – chux

回答

5

您使用feof()的方式似乎很受初學者歡迎,但不幸的是仍然是錯誤的。

feof()的要點是要在之後查詢發生I/O錯誤,如果發生I/O錯誤是因爲已達到文件結尾。應該使用而不是來過早地決定文件是否已經結束。

只是做讀,直到它失敗。

while(fscanf(clientDataFile1, "%d%s%lf", &accountNum, name, &balance) == 3) 
{ 
    printf("%-10d%-13s%.2lf\n", accountNum, name, balance); 
} 
+0

因此,我應該怎麼做才能知道是否已到達文件末尾。 – Maddy

+0

@Maddy你確實看到我的代碼,對吧?當達到文件結束時,'fscanf()'將失敗,你不需要尋找那個特定的失敗。 – unwind

+0

您的解決方案僅限於已知的值。如果我們必須檢查它們的動態文件和記錄,該怎麼辦...... – Maddy

4

閱讀從@unwind答案後,我得到了好奇,什麼feof()呢,爲什麼這會導致最後一個記錄的雙打印。

cplusplus.com:「請注意,流的內部位置指示器可以指向結束文件用於下一個操作,不過,結束文件的指示符可以不被置位,直到操作試圖在該讀取點。」

所以你達到EOF,並打印最後一個記錄,但feof()已檢查尚未設置該標誌。然後,在循環的下一次迭代中,您執行一個fscanf,由於過去EOF而失敗。這種失敗會導致標誌被設置,使得這是循環的最後一次迭代。這種迭代仍然打印什麼是已經保存在accountnumnamebalance變量,所以你看到的最後一個記錄的兩倍。

+0

它可以工作任何方式。想象一下,最後一行可能有或沒有換行符的文本文件。直到你閱讀最後一行,是否有任何內容,你纔會知道。 – stark

1

簡短的回答:你的while循環應該是這樣的:

while (!feof(clientDataFile1)) 
{ 
    if (EOF == fscanf(clientDataFile1, "%d%s%lf", &accountNum, name, &balance)) 
    break ; 

    printf("%-10d%-13s%.2lf\n", accountNum, name, balance); 
} 
+0

'while(1){if(EOF == fscanf(...)break; ...}'會做同樣的事情。不需要'feof()'。 – chux

+0

@chux:正確,但如果只留下'feof'「,我就離開了。 –

0

一段時間(的fscanf(clientDataFile, 「%d%S%LF」,& accountNum,名稱,&平衡)= EOF) 的printf( 「%-10D%-13s%.2lf \ n」 個,accountNum,姓名,平衡);

實際上EOF的值是-1和fscanf()函數返回inputed變量的數目。所以,當fscanf()的值等於-1的EOF並且因此實現了while的中斷時,表達式!=計算0。