2015-07-04 45 views
3

我正在製作一個加載小文本文件的c程序。我將文本文件的讀取內容存儲在char數組中。這是加載文件的函數。字符數組中的C隨機字符

void load_text_file(char* filename) { 
    FILE *fp; 
    char *buf = malloc(255 * sizeof(char)); 
    if (!buf) return NULL; 

    fp = fopen(filename, "r"); 
    fgets(buf, 255, (FILE*)fp); 

    int i; 
    for(i=0;i<255;i++) { 
     printf("%d - %c\n", i, buf[i]); 
    } 
} 

當for循環打印輸出時,會發生這種情況。 (這是輸出的一個縮短的版本,我不希望把所有255個字符的這個問題。)

0 - H 
1 - e 
2 - l 
3 - l 
4 - o 
5 - 
6 - W 
7 - o 
8 - r 
9 - l 
10 - d 
11 - ! 
//Random chars past this point 
12 - 
13 - 
14 - „ 
15 - 
16 - „ 
//etc... etc... etc... 
96 - Å 
97 - 
98 - 
99 - Å 
100 - å 
101 - è 
102 - 
//etc... etc... etc... 
//all the way up to 255 chars 

我不能確定是什麼原因造成這一點。
我想知道是什麼導致這種情況,以及我如何解決這個問題。

+2

假設您正在閱讀的文件只有12個字節長。你期望陣列在字節#12以外的區域保持什麼?爲什麼? –

+0

你的函數泄漏內存。那麼爲什麼''返回NULL;'在'void'函數中?只需將你的緩衝區聲明爲一個靜態變量:'static char buf [255];',並且使用'sizeof(buf)'代替全部硬編碼。您不必處理動態分配,只要您打算保持緩衝區長度不變,就完全不必要。 –

+0

OT:'load_text_file()'錯過了'fclose()''fp'。 – alk

回答

1

你觀察什麼是不足爲奇的,讓我們看看你的代碼:

fgets(buf, 255, (FILE*)fp); 

首先沒有理由投fp(FILE*)fp被定義爲正確的類型,並且投射指針是一個壞習慣,通常會導致不可讀和錯誤的代碼。

fgets(buf, 255, fp)嘗試從流中讀取多達254個字符,在第一個'\n'處停止。它返回一個指向buf的指針,除非不能讀取字符,在這種情況下,緩衝區的內容是不確定的,並返回NULL

您應該測試此返回值以驗證字符確實是從流中讀取的,否則緩衝區的內容可能是隨機字符,可能發生的情況是發生在已發現可用內存的堆空間中。

fgets()遇到行進料,或者如果254個字符已被存儲到緩衝器,它存儲一個'\0'字節之後的字符讀取並返回一個指向緩衝區的指針。超出此NUL字節的緩衝區的內容是不確定的,如上述,他們可能是NUL或明顯的隨機字符,或任何東西......

你應該重寫你的循環這種方式只轉儲有意義的字符:

void load_text_file(const char *filename) { 
    char *buf = malloc(255 * sizeof(char)); 
    if (!buf) { printf("could not allocate memory\n"); return; } 

    FILE *fp = fopen(filename, "r"); 
    if (!fp) { printf("could not open file\n"); return; } 

    if (fgets(buf, 255, (FILE*)fp)) { 
     for (int i = 0; buf[i] != '\0'; i++) { 
      printf("%d - %c\n", i, buf[i]); 
     } 
     ... // do something else with `buf` 
    } 
    fclose(fp); 
    free(buf); 
} 
5

你應該打印buf爲:

printf("%s\n", buf); 

你看到的垃圾未初始化的RAM內存與malloc分配給您的buf,而不是由fgets感動。

0

fgets會讀取到您的信息流的結尾(本例中的前254個字符)或直到遇到第一個'\0'。如果你正在讀取任何'\0',你會得到垃圾值作爲輸出。因此,直到找到第一個,您應該執行該循環,而不是執行循環直到255。