C语言中如何遍历TXT文件并将行数据存入单链表节点?
问题分析与解决方案
代码中的核心问题
- 格式串与文件行不匹配:你的文件每行仅包含Tag、Name、Surname、Age四个字段,但代码中
sscanf格式串额外加入了Balance: %d,导致无法匹配行内容,返回值小于预期,触发失败提示。 - 结构体成员不匹配:定义的
Node结构体中没有balance成员,但代码中却赋值new_node->balance = balance,这会导致编译错误或非法内存访问。 - 字符串成员未分配内存:
Node中的name和surname是char*类型,直接用strcpy复制会写入未分配的内存,引发野指针或内存错误。 - 冗余参数传递:
insert_account函数传入了balance,但结构体和文件中都没有这个字段,属于无效参数。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Node { int age; char *name; char *surname; int tag; struct Node *next; // 补充链表节点必备的next指针 } Node; Node *root_of_tags = NULL; // 链表根节点 // 修正后的链表插入函数 void insert_account(Node **root, int tag, char *name, char *surname, int age) { Node *new_node = malloc(sizeof(Node)); if (new_node == NULL) { perror("malloc failed for Node"); exit(EXIT_FAILURE); } // 为字符串成员分配内存 new_node->name = malloc(strlen(name) + 1); new_node->surname = malloc(strlen(surname) + 1); if (new_node->name == NULL || new_node->surname == NULL) { perror("malloc failed for string"); // 释放已分配的内存避免泄漏 free(new_node->name); free(new_node->surname); free(new_node); exit(EXIT_FAILURE); } // 复制数据到节点 strcpy(new_node->name, name); strcpy(new_node->surname, surname); new_node->tag = tag; new_node->age = age; new_node->next = *root; // 头插法示例 *root = new_node; } void file_reading(FILE **account) { int tag, age; char name[50], surname[50]; *account = fopen("account.txt", "r"); if (*account == NULL) { perror("Failed to open account.txt"); exit(EXIT_FAILURE); } char line[200]; while (fgets(line, sizeof(line), *account) != NULL) { // 去除换行符,避免干扰sscanf匹配 size_t line_len = strlen(line); if (line_len > 0 && line[line_len - 1] == '\n') { line[line_len - 1] = '\0'; } int consumed = 0; // 格式串严格匹配文件行结构 int match_count = sscanf(line, "Tag: %d, Name: %s, Surname: %s, Age: %d%n", &tag, name, surname, &age, &consumed); // 验证是否匹配全部4个字段,且整行无多余字符 if (match_count == 4 && consumed == strlen(line)) { insert_account(&root_of_tags, tag, name, surname, age); } else { printf("Invalid line: %s\n", line); } } } // 打印链表用于验证结果 void print_linked_list(Node *root) { Node *current = root; while (current != NULL) { printf("Tag: %d, Name: %s, Surname: %s, Age: %d\n", current->tag, current->name, current->surname, current->age); current = current->next; } } // 释放链表内存避免泄漏 void free_linked_list(Node *root) { Node *temp; while (root != NULL) { temp = root; root = root->next; free(temp->name); free(temp->surname); free(temp); } } int main() { FILE *account; file_reading(&account); print_linked_list(root_of_tags); free_linked_list(root_of_tags); fclose(account); return 0; }
关键修正说明
- 格式串匹配:将
sscanf格式串调整为与文件行完全一致的结构,移除多余的Balance字段。 - 内存分配:为
Node的字符串成员单独分配内存,确保strcpy有合法的写入空间。 - 冗余清理:删除所有与
balance相关的变量、赋值和参数,严格匹配Node结构体定义。 - 行处理优化:去除
fgets读取的换行符,同时通过consumed变量验证整行是否被正确解析,排除无效行。 - 错误处理增强:增加内存分配失败的检查和资源释放逻辑,避免内存泄漏;用
perror输出更明确的错误信息。
内容的提问来源于stack exchange,提问作者Jovan Dejanović
相关产品推荐
相关产品推荐

