You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键修正说明

  1. 格式串匹配:将sscanf格式串调整为与文件行完全一致的结构,移除多余的Balance字段。
  2. 内存分配:为Node的字符串成员单独分配内存,确保strcpy有合法的写入空间。
  3. 冗余清理:删除所有与balance相关的变量、赋值和参数,严格匹配Node结构体定义。
  4. 行处理优化:去除fgets读取的换行符,同时通过consumed变量验证整行是否被正确解析,排除无效行。
  5. 错误处理增强:增加内存分配失败的检查和资源释放逻辑,避免内存泄漏;用perror输出更明确的错误信息。

内容的提问来源于stack exchange,提问作者Jovan Dejanović

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:27:51