为什么从文件函数读取崩溃?
试图从文件中读取多行以将它们存储在由字符串元素组成的结构中,但是当我运行程序时它只是崩溃而我不知道原因。
有问题的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]);
这里的subscript
和value
参数是否以某种方式初始化? 检查你的init_hashtbl()
。
编辑
既然你发布了init_hashtbl
:
for(i = 0; i<(SIZE*2); i++){ strcpy(hashtbl[i].subscript, string[i]); i++; }
您正在使用字符串文字初始化subscript
和value
,它们指向只读内存位置, 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 line
的sizeof line
,换行符将被添加到行中。 你很可能不想拥有它。 摆脱换行的一种方法是:
fgets(line, sizeof line, f); int len = strlen(line); if(line[len - 1] == '\n') line[len - 1] = 0;