2017-02-11 85 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; 
}