2014-01-09 93 views
0

我正在用C編寫一個程序,它應該從任意長度的文件中讀取雙精度數組。如何停止在EOF?我已經嘗試使用FEOF,但後來讀討論:如何將c中的整個文件讀入數組數組

Why is 「while (!feof (file))」 always wrong?

How does C handle EOF?

話又說回來,他們關心的字符串,而不是數字。所以當讀取形式爲「4 23.3 2 1.2」的文件時,如何聲明循環條件,以便我的數組A具有來自文件的所有數字並且沒有更多(也就是迭代器N = A的長度)?

下面是我用feof編寫的代碼部分,它在A中產生了太多的條目。重新分配部分基於http://www.cplusplus.com/reference/cstdlib/realloc/示例。

int N = 0;  

double *A = NULL; 
double *more_space; 
double buff = 0; 

FILE *data; 
data = fopen(data.dat,"r"); 

while(feof(data) == 0) { 
    fscanf(data, "%lg", &buff); 
    more_space = realloc(A, (N+1)*sizeof(double)); 
    A = more_space; 
    A[N] = buff; 
    N++; 
} 
+0

結果嘗試讀取大緩衝的時間,而且比scanfing它... – vrdhn

+1

'而(!FEOF(流)){...} '由於邏輯問題是錯誤的,它不是特定於字符串或數字。邏輯僞代碼應該是'while(有更多的數據){做一些與數據有關的事情}當沒有更多的數據時,循環終止。只有在那個時候檢查feof纔有意義。例如,如果你的循環結束了,但你沒有完成,也許在你的文件中有一些無效的數據,或者可能發生讀取錯誤 – Brandin

回答

1

當您擊中eof(或其他問題)時,fscanf的返回值爲-1,因此請嘗試while(fscanf(…) >= 0)作爲您的外部循環。 (無論您接受零回報值還是不取決於您希望如何處理不良數據 - 正如其他海報所指出的那樣,如果沒有轉換數字,您將得到0.

我喜歡使用'大於或等於'測試(而不是測試==1),因爲如果您將scanf格式更改爲從輸入行讀取兩個項目,它不會中斷;另一方面,您可能會爭辯說最好驗證您始終仔細閱讀正確的參數個數,只要你改變了少量參數,最好讓你的程序「快速失敗」,而不是稍後有一些神祕的失敗,如果你輸入錯誤的話,這是一個風格問題。 ,以及這是否是一次性代碼或生產代碼..

+0

所有引用說它返回EOF,假設EOF有一個特定的值,如-1是錯誤的 – Brandin

+1

@Brandin是真實的,但我不知道爲什麼你將此評論附加到我的文章:我沒有說要測試對-1 ,我說要使用大於0(或大於1)的檢查。標準*做*保證無論EOF是什麼,它都是負面的。(和fscanf的任何其他返回值都是0或正數) – JVMATL

+1

它與帖子相關。個人而言,我喜歡使用格式爲「%f%f%f%c」的額外參數,然後確保返回值爲3.這樣,您確定沒有額外的「垃圾「後面的數據感興趣。 – Brandin

0

你應該這樣做:

while (fscanf(data, "%lg", &buff) == 1) 

這樣,如果你打一個「非數字」,那麼它會無限,而不是停止循環! ... fscanf將檢查EOF,它會爲你打破循環。

1

只要fscanf告訴你沒有更多數據需要讀取就停止。它的返回值表示它讀取的項目的數量,或者如果達到文件結尾或出現讀取錯誤,則返回EOF。因此,由於您在每次通話中只讀取一個項目,只要閱讀成功,您將獲得1個項目。

while (fscanf(data, "%lg", &buff) == 1) { 
    ... 
} 

您可能希望將返回值存儲在一個變量,以驗證讀數是否停止由於檔案結尾還是因爲雙解析失敗。

+1

即使文件的末尾尚未到達,fscanf也會返回EOF 。例如,如果發生匹配錯誤或者由於某些其他原因無法讀取文件。 – Brandin

0

或者到其他的答案,讀取整個文件:

int32_t readFile (char* filename, uint8_t** contentPtr, int32_t* sizePtr) 
{ 
    int32_t ret = 0; 
    struct stat st; 
    FILE *file = NULL; 
    uint8_t* content = NULL; 

    memset (&st, 0, sizeof (struct stat)); 

    ret = stat(filename, &st); 
    if(ret < 0) { 
    return -1; 
    } 

    file = fopen64(filename, "rb"); 
    if (file == NULL) { 
    return -1; 
    } 

    content = calloc (st.st_size+10, sizeof (uint8_t)); 

    ret = fread (content, 1, st.st_size, file); 
    fclose(file); 
    if(ret != st.st_size) { 
    free(content); 

    return -1; 
    } 

    *contentPtr = content; 
    if (sizePtr != NULL) { 
    *sizePtr = st.st_size; 
    } 

    return 0; 
} 

然後用sscanf()處理緩衝區的內容。

1

在掃描過程中,保存的fscanf()

int cnt; 
double d; 
while ((cnt = fscanf("%f", &d)) == 1) { 
    more_space = realloc(A, (N+1)*sizeof(double)); 
    if (more_space == NULL) Handle_MemoryError(); 
    A = more_space; 
    A[N] = buff; 
    N++; 
} 
if (cnt == 0) Handle_BadDataError();