使用strtok读取txt初始化链表时name为null但printf输出正常
问题根因
你代码里存在4个核心错误导致name输出为null:
- 错误1:直接把
strtok返回的指针赋值给heal->name,strtok返回的指针指向栈上的局部数组line,每次fgets循环都会覆盖line的内容,函数执行完line内存会被回收,后续访问name就是野指针。 - 错误2:一行文本对应1个
Heals结构体,但你在内部strtok循环里每次迭代都新建Heals,导致一行拆分出的name和heal值被存到了两个不同的Heals实例里,最终挂到链表的实例只有heal值、没有name赋值。 - 错误3:链表没有做节点串联,每次都直接把新节点赋值给
ListeHeals->first,旧节点直接丢失,最终链表只会保留最后一行的heal数据。 - 错误4:
fopen打开文件失败后没有终止流程,会触发后续空指针访问崩溃。
修复后的initHeals代码
#include "heals.h" ListeHeals* initHeals() { ListeHeals* listeHeals = malloc(sizeof(*listeHeals)); // 初始化链表头 listeHeals->first = NULL; Heals* tail = NULL; // 用尾指针方便串联节点 char const* const fileName = "items/heals.txt"; FILE* file = fopen(fileName, "r"); if (file == NULL) { printf("Fichier non ouvert"); exit(EXIT_FAILURE); // 打开失败直接退出 } char line[256]; const char * separator = "|"; while (fgets(line, sizeof(line), file)) { // 每行先新建1个Heals实例 Heals* heal = malloc(sizeof(*heal)); heal->next = NULL; int count = 0; char* strElement = strtok (line, separator); while (strElement != NULL) { if(count == 0) { printf("%s\n", strElement); // 拷贝字符串到堆上,不要直接赋值指针 heal->name = strdup(strElement); } else if(count == 1) { heal->heal = atoi(strElement); } strElement = strtok (NULL, separator); count += 1; } // 把新节点挂到链表 if (listeHeals->first == NULL) { listeHeals->first = heal; } else { tail->next = heal; } tail = heal; } fclose(file); return listeHeals; }
补充说明
如果你的环境不支持strdup,可以替换为手动分配内存拷贝:
heal->name = malloc(strlen(strElement)+1); strcpy(heal->name, strElement);
注意后续销毁链表时,要先释放每个节点的name内存,再释放节点本身,避免内存泄漏。
内容的提问来源于stack exchange,提问作者quentin coqueran
相关产品推荐
相关产品推荐

