2013-06-27 121 views
1

爲什麼此代碼的輸出是內存中的一些隨機字?從文件中獲取字符串

void conc() 
{ 
    FILE *source = fopen("c.txt", "r+"); 
    if(!source) 
    { 
     printf("Ficheiro não encontrado"); 
     return; 
    } 

    short i = 0; 
    while(fgetc(source) != EOF) 
     i++; 

    char tmp_str[i]; 
    fgets(tmp_str, i, source); 
    fclose(source); 
    printf("%s", tmp_str); 
} 

這應該給我的文件的內容,我認爲。

+0

你編譯了你的應用程序嗎? –

+0

是你的'while'循環嗎? – Bill

回答

7

因爲在使用fgetc()遍歷文件後,位置指示符位於文件結束處。 fgets()沒有什麼可讀的。您需要重置它,以便使用rewind(source);指向開頭。

順便說一下,不要通過使用fgetc()循環文件,這是一個非常醜陋的解決方案。使用fseek()ftell()lseek()而不是獲取文件的大小:

fseek(source, SEEK_END, 0); 
long size = ftell(source); 
fseek(source, SEEK_SET, 0); // or rewind(source); 

替代:

off_t size = lseek(source, SEEK_END, 0); 
rewind(source); 
+0

哦!那些小(BIG)的東西......非常感謝你,先生! –

+2

@TelmoVaz不客氣。順便說一句,不要循環遍歷文件兩次,而是使用'ftell()'。 – 2013-06-27 12:39:11

+1

+1。 – 0decimal0

0

fgetc()後 - 環已達到EOF,如果你不fseek(source, 0l, SEEK_SET)回開始你將不會獲得更多的數據。 無論如何,你應該避免兩次閱讀文件。改用fstat(fileno(source), ...)來確定文件大小。

1

使用rewind(source);fgets(tmp_str, i, source);

0

龜etc從流中讀取一個字符。 fgets從流中讀取一個字符串。

現在在您的代碼中,您正在迭代文件的末尾。因此,對流上fgets的調用將簡單地返回NULL並保持緩衝區內容不變。在你的情況下,你的緩衝區不會被初始化。這解釋了你所看到的隨機值。

而不是閱讀與龜etc完整的文件內容,以獲得字符數,我建議使用FSEEK/FTELL(查看從此thread答案)

0

你的代碼是錯誤的。正如之前所說:

  1. 你不應該讀文件兩次
  2. 要分配陣列動態如果您需要您必須使用new操作符(在C++) 或函數malloc(C語言)

代碼讀取文件內容,嘗試下(很抱歉,但我沒有編譯它無論如何它應該很好地工作。):

FILE* source = fopen("c.txt", "r+b"); 
if(!source){return;} 
fseek(source, 0, SEEK_END); 
size_t filesize = ftell(source); 
fseek(source, 0, SEEK_SET); 
char* buf = new char[filesize+1]; // +1 is for '/0' 
fread(buf, sizeof(char), filesize, source); 
fclose(source); 
buf[filesize]=0; 
printf("%s", buf); 
delete buf; 
0

每次調用龜etc(時間)你提前內部文件指針再一個字符。在while()循環結束時,文件指針將位於文件的末尾。隨後的讀入文件句柄的調用將失敗並出現EOF條件。

的與fgets手冊說:

如果在試圖讀取一個字符遇到結束文件時,EOF指示符被設定(FEOF)。如果在任何字符被讀取之前發生這種情況,返回的指針是一個空指針(並且str的內容保持不變)。

其結果是tmp_str保持不變。調用printf時返回的垃圾實際上是conc()函數堆棧的一部分。

問題的解決方案是在調用fgets()之前使用fseek()重新引導文件指針。

fseek(source, 0, SEEK_SET); 

然後一個更好的辦法讓你的文件的大小將是FSEEK到文件的末尾,並使用FTELL來獲得當前位置:

long size; 
fseek(source, 0, SEEK_END); 
size = ftell(source); 

這是說,你的代碼仍然有問題。當你在堆棧上分配(函數的本地變量)時,你必須在編譯時告訴變量的大小。這裏你的編譯器分配一個長度爲0的字符數組。我建議你調查動態分配malloc關鍵字如果你使用C++編碼。

一個適當的分配是這樣的:

char *tmp_str = malloc(size); 
// Here you read the file 
free(tmp_str); 

一個簡單的解決方案可能是預先分配的字符串大到足以容納你的文件。

char tmp_str[1024 * 100]; // 100Kb 

然後使用大小變量我們早點起牀來檢查文件將適合tmp_str讀數。