C语言从文件读取创建链表时最后一行重复读取问题求助
解决读取文件创建链表时最后一行重复的问题
嘿,这个坑我之前也踩过!核心问题出在你用while(!feof(fp))作为循环条件——feof()的逻辑是只有当你尝试读取超过文件末尾之后,才会触发文件结束标记。所以当你读完最后一行有效数据时,feof(fp)还是false,会再跑一次循环。这时候fscanf读取失败,但你还是执行了打印和内存分配操作,导致最后一行的旧数据被重复输出(其实是上一次的内容没被覆盖,因为这次读取没成功)。
给你几个关键修改点,彻底解决这个问题:
1. 用fscanf的返回值替代feof作为循环条件
fscanf会返回成功读取的参数个数,我们要读取name、id、marks三个参数,所以当返回值等于3时,才说明读取到了有效数据。直接用这个作为循环判断条件,就能精准控制循环次数。
2. 修复链表结尾,避免空节点
原代码每次创建节点都直接分配下一个节点,会导致链表最后多一个空节点,记得把最后一个节点的next设为NULL,符合链表规范。
3. 补上原代码的其他小漏洞
比如没检查文件是否成功打开、没关闭文件、struct定义末尾少分号、void main不符合C标准等,这些细节也容易引发问题。
下面是修改后的完整代码:
#include <stdio.h> #include <stdlib.h> struct student { int id; char name[20]; float marks; struct student *next; // 补上缺失的分号 }; typedef struct student node; int main() { // 改用int main符合C标准规范 node *head = NULL; void read(node *p); void print(node *p); int count(node *p); head = (node *)malloc(sizeof(node)); if(head == NULL) { // 检查内存分配是否成功 printf("Memory allocation failed!\n"); return 1; } read(head); // 可调用print函数验证链表输出 // print(head); return 0; } void read(node *list) { FILE *fp; char filename[30]; int read_result; printf("input file name:"); scanf("%s", filename); fp = fopen(filename, "r"); if(fp == NULL) { // 检查文件是否成功打开 printf("Failed to open file!\n"); return; } // 先读取第一组数据 read_result = fscanf(fp, "%s %d %f", list->name, &list->id, &list->marks); while(read_result == 3) { printf("%s \t%d \t%f\n", list->name, list->id, list->marks); // 分配下一个节点并检查内存 list->next = (node*)malloc(sizeof(node)); if(list->next == NULL) { printf("Memory allocation failed!\n"); fclose(fp); return; } list = list->next; // 读取下一组数据 read_result = fscanf(fp, "%s %d %f", list->name, &list->id, &list->marks); } // 最后一个节点的next设为NULL,结束链表 list->next = NULL; fclose(fp); // 关闭文件释放资源 } // 可保留你的print、count函数,此处省略
这样修改后,就不会再重复读取最后一行了,同时也修复了几个潜在的bug。
内容的提问来源于stack exchange,提问作者ThisIsHard
相关产品推荐
相关产品推荐

