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

C语言单链表从文件加载数据问题:重启后无法恢复链表数据

问题分析与修复方案

核心问题点

  1. 文件读写格式不匹配:插入数据时写入带描述文本的内容(如visitor info has been added: ...),但读取时直接按四个字符串解析,导致读取内容完全错误,无法还原数据。
  2. 文件路径不一致:插入时写入output.txt,读取时打开ticket.txt,文件不对应,读不到之前存储的数据。
  3. 链表传递与构建错误:readfile用值传递指针,无法更新主函数的链表头;构建链表时未遍历到尾部,新节点不断覆盖前一个节点的next,最终链表仅保留最后一个节点。
  4. 缺少错误处理:未判断文件是否成功打开,可能导致空指针访问崩溃。

修正后的代码

1. 修正插入函数(addinfo)

调整文件写入格式为纯数据,统一使用ticket.txt存储可恢复的数据:

tick *addinfo(tick *previous, char* serial, char* ticketno, char* name, char* id)
{
    tick *info = malloc(sizeof(tick));
    info->nextPtr = NULL;
    info->visitor.SrNo = strdup(serial);
    info->visitor.ticketNo = strdup(ticketno);
    info->visitor.Name = strdup(name);
    info->visitor.ID = strdup(id);

    if (previous != NULL)
    {
        previous->nextPtr = info;
    }

    printf("visitor info has been added: %s %s %s %s\n", info->visitor.SrNo, info->visitor.ticketNo, info->visitor.Name, info->visitor.ID);
    
    // 写入纯数据到ticket.txt,用于后续恢复
    FILE *ptroutfile = fopen("ticket.txt", "a");
    if (ptroutfile != NULL)
    {
        fprintf(ptroutfile, "%s %s %s %s\n", info->visitor.SrNo, info->visitor.ticketNo, info->visitor.Name, info->visitor.ID);
        fclose(ptroutfile);
    }

    return info;
}

2. 修正读取文件函数(readfile)

改为返回链表头指针,正确遍历链表尾部添加节点,增加文件打开失败判断:

tick* readfile()
{
    tick *startPtr = NULL;
    tick *currentPtr = NULL;
    FILE* cfptr = fopen("ticket.txt", "r");
    
    if (cfptr == NULL)
    {
        printf("No existing data file found.\n");
        return startPtr;
    }

    char srno[20], ticketNo[20], name[30], id[20];
    while (fscanf(cfptr, "%s %s %s %s", srno, ticketNo, name, id) == 4)
    {
        tick *info = malloc(sizeof(tick));
        info->nextPtr = NULL;
        info->visitor.SrNo = strdup(srno);
        info->visitor.ticketNo = strdup(ticketNo);
        info->visitor.Name = strdup(name);
        info->visitor.ID = strdup(id);

        if (startPtr == NULL)
        {
            // 第一个节点作为链表头
            startPtr = info;
            currentPtr = info;
        }
        else
        {
            // 追加到链表尾部
            currentPtr->nextPtr = info;
            currentPtr = info;
        }
    }

    fclose(cfptr);
    return startPtr;
}

3. 修正主函数调用

接收readfile返回的链表头指针,可正常恢复数据:

int main ()
{
    tick *visitorinfo = NULL;
    // 从文件恢复链表
    visitorinfo = readfile();

    // 测试:遍历打印恢复的数据
    tick *temp = visitorinfo;
    while (temp != NULL)
    {
        printf("Loaded data: %s %s %s %s\n", temp->visitor.SrNo, temp->visitor.ticketNo, temp->visitor.Name, temp->visitor.ID);
        temp = temp->nextPtr;
    }

    // 后续可调用addinfo添加新节点,需注意维护尾指针或遍历到尾部再添加
    // 程序结束前需释放链表内存(自行实现)
    return 0;
}

额外说明

  • 若需要保留日志式的输出,可以同时写入output.txt(带描述)和ticket.txt(纯数据)。
  • 若数据包含空格,不能用fscanf("%s")读取,需改用fgets配合字符串分割处理。
  • 程序退出前务必释放链表所有节点的内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者user19766923

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:01:07