2017-02-11 67 views
0

這非常奇怪 - 我從文件中獲取行,將它們打印到屏幕上,並將它們存儲在數組中。將它們打印到屏幕上時,一切看起來都很好,但在數組中,每個元素都設置爲文件的最後一行。逐行讀取文件只返回最後一行

文件看起來是這樣的:

DarkMatter 
Fire 
Water 
Air 
Earth 
Plasma 
Wind 

這是我的代碼:

char *rooms[7]; 
FILE *roomFile = fopen("rooms.txt", "r"); 
char name[20]; 
for(i=0; i<7; i++) { 
    fgets(name, sizeof name, roomFile); 
    rooms[i] = name; 
    printf("%s", rooms[i]); 
} 
for(i=0; i<7; i++) { 
    printf("%s\n", rooms[i]); 
} 

當文件環路一切正常時打印rooms[i],但一旦我嘗試之後打印室陣列,每個元素都設置爲wind。這怎麼可能?

輸出:

DarkMatter 
Fire 
Water 
Air 
Earth 
Plasma 
Wind 
Wind 

Wind 

Wind 

Wind 

Wind 

Wind 

Wind 

回答

0

更換

rooms[i] = name; 

//rooms[i] = name; 
rooms[i] = malloc(20); 
strcpy(rooms[i], name); 

原因

聲明rooms[i] = name;只是指示指針rooms[i]等於指針(或數組)name。所以有效的每個rooms[0], rooms[1], rooms[2]擁有name的地址。在for循環的每次迭代中,name都會被複制一個不同的字符串。但是name指向的地址,因此rooms的所有元素保持不變。

+2

您無法檢查分配錯誤。你也沒有提到「免費」分配的必要性。在示例代碼中鼓勵這種鬆散是不好的。最好提一下'strdup()',它不太容易出錯。 –

0

這裏有幾個問題需要解決。您已將rooms聲明爲指向char的指針數組,但將其視爲2維數組。您可以使用malloc空間來存儲字符串,但將rooms簡單地聲明爲2維數組會更簡單。

當您打開文件時,您應該始終檢查以確保文件成功打開。如果您選擇分配內存,則應同樣檢查分配錯誤。您還應該檢查由fgets()返回的錯誤值。

在第一個循環中,將緩衝區name的內容分配給rooms[i],這是一個指針。但你不能指定如果更改聲明rooms向陣列中C.這樣:

char rooms[7][20] 

那麼你可以使用strcpy()name內容複製到rooms[i]。或者,您可以使用strdup()複製緩衝區的內容。這樣做的好處是strdup()爲您分配存儲空間,但您仍然必須記住稍後釋放內存。您也可以自己分配內存,並將name的內容複製到分配的區域。

這是您的代碼的修改版本,使用最簡單的方法,即將rooms簡單地聲明爲二維數組。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) 
{ 
    char rooms[7][20]; 
    FILE *roomFile = fopen("rooms.txt", "r"); 
    if (roomFile == NULL) {      // error checking 
     fprintf(stderr, "Error opening file\n"); 
     exit(EXIT_FAILURE); 
    } 

    char name[20]; 
    for(size_t i = 0; i < 7; i++) { 
     fgets(name, sizeof name, roomFile); 
     strcpy(rooms[i], name); 
     printf("%s", rooms[i]); 
    } 
    for(size_t i = 0; i < 7; i++) { 
     printf("%s\n", rooms[i]); 
    } 

    return 0; 
}