为什么从文件函数读取崩溃?

试图从文件中读取多行以将它们存储在由字符串元素组成的结构中,但是当我运行程序时它只是崩溃而我不知道原因。

有问题的function:

Hashtbl* loadfromfile(Hashtbl* hashtbl, char *path){ int i = 0; char line[100]; char* string[40]; FILE *f = fopen(path, "r"); if(f == NULL){ printf("FILE NO FOUND!"); }else{ while(fgets(line, sizeof(line), f)!=NULL){ strcpy(string[i],line); i++; } fclose(f); for(i = 0; i<(SIZE*2); i++){ strcpy(hashtbl[i].subscript, string[i]); i++; } for(i = 1; i<(SIZE*2); i++){ strcpy(hashtbl[i].value, string[i]); i++; } return hashtbl; } } 

main.c中:

 #include  #include  #include "hashtable.h" int main() { Hashtbl* numbers; numbers = init_hashtbl(); //init_hashtable initialises numbers loadfromfile(numbers, "test.txt"); for(int i = 0; i<SIZE; i++) { printf("%s1", numbers[i].subscript); printf("%s2\n", numbers[i].value); } } 

哈希表结构:

 typedef struct Hashtbls{ char *subscript; char *value; } Hashtbl; 

init_hasthable函数:

  Hashtbl* init_hashtbl(){ Hashtbl* hashtbl; hashtbl = calloc(SIZE, sizeof(Hashtbl)); for(int i = 0; i<SIZE; i++){ hashtbl[i].subscript = "ZERO"; hashtbl[i].value = "ZERO"; } return hashtbl; } 

你在这里遇到了很多问题:

 if(f == NULL){ printf("FILE NO FOUND!"); } 

如果文件无法打开,则无法继续。 也可以稍后打印消息,使用printf("FILE NOT FOUND!\n"); 代替。

 char* string[40]; ... while(fgets(line, sizeof(line), f)!=NULL){ strcpy(string[i],line); i++; } 

string是一个未初始化的指针数组,你不能在那里写任何东西。 你应该做

 while(fgets(line, sizeof line, f)) { string[i] = malloc(strlen(line) + 1); if(string[i] == NULL) { // error handling is needed } strcpy(string[i], line); i++; if(i == sizeof string / sizeof *string) break; } // or if your system has strdup while(fgets(line, sizeof line, f)) { string[i] = strdup(line); if(string[i] == NULL) { // error handling is needed } i++; if(i == sizeof string / sizeof *string) break; } 

此外,您不会检查是否阅读超过40行。 我用最后一个做了那个。 sizeof array / sizeof *array返回数组可以容纳的元素数。 请注意,这仅适用于数组,而不适用于指针,因为通常sizeof array != sizeof pointer 。 此外,不要忘记释放分配的内存。

 strcpy(hashtbl[i].subscript, string[i]); ... strcpy(hashtbl[i].value, string[i]); 

这里的subscriptvalue参数是否以某种方式初始化? 检查你的init_hashtbl()


编辑

既然你发布了init_hashtbl

 for(i = 0; i<(SIZE*2); i++){ strcpy(hashtbl[i].subscript, string[i]); i++; } 

您正在使用字符串文字初始化subscriptvalue ,它们指向只读内存位置, strcpy将失败。 您必须使用malloc分配内存或使用数组更改结构。

选项1

保留结构,更改init_hashtbl

 Hashtbl* init_hashtbl(){ Hashtbl* hashtbl; hashtbl = calloc(SIZE, sizeof(Hashtbl)); for(int i = 0; i 

您应该始终检查malloc / calloc的返回值。 此外,问题是如果要复制长度超过SOME_MAXIMAL_LENGTH的字符串,则会出现缓冲区溢出。 所以你应该在阅读例程中使用realloc:

 for(i = 0; i<(SIZE*2); i++){ char *tmp = realloc(hashtbl[i].subscript, strlen(string[i]) + 1); if(tmp == NULL) { // error handling } hashtbl[i].subscript = tmp; strcpy(hashtbl[i].subscript, string[i]); i++; } 

如果你不想在这里处理realloc ,你必须确保没有string[i]SOME_MAXIMAL_LENGTH更长。

选项2

改变你的结构和init:

 typedef struct Hashtbls{ char subscript[SOME_MAXIMAL_LENGTH]; char value[SOME_MAXIMAL_LENGTH]; } Hashtbl; Hashtbl* init_hashtbl(){ Hashtbl* hashtbl; hashtbl = calloc(SIZE, sizeof(Hashtbl)); for(int i = 0; i 

然后在loadfromfile你不必处理如上所示的realloc ,你可以保留你的代码。 但是,您必须检查没有string[i]长于SOME_MAXIMAL_LENGTH - 1 ,否则缓冲区溢出。

最后一点, fgets读取整行,假设行的长度小于sizeof linesizeof line ,换行符将被添加到行中。 你很可能不想拥有它。 摆脱换行的一种方法是:

 fgets(line, sizeof line, f); int len = strlen(line); if(line[len - 1] == '\n') line[len - 1] = 0;