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

C语言任务管理器:结构体数据文件存读异常(存正常读失效)

任务管理器数据加载与保存问题

我正在开发一款任务管理器,用于存储任务与员工信息,已定义两个结构体。需求为:启动程序时从文件将数据加载至结构体,关闭程序时将结构体数据保存回文件。目前saveData函数可正常运行,但GetData函数无法正常工作;此外,即便文件打开时未将数据加载到结构体,关闭程序时仍会保存数据且不会覆盖原有内容。

现有代码

从文件加载数据的函数

void GetData(){
    FILE *fptr = fopen("Manager_Data.txt", "r");
    for (int i = 0;i < TAM_EMP; i++) {
        fscanf(fptr, "%d,%s,%s,%d,%s,%s,%s,%d
", &employees[i].ID, employees[i].name, employees[i].date, &employees[i].phone, employees[i].email, employees[i].local, employees[i].depart, &employees[i].availability);
    }
    fclose(fptr);
}

将数据保存至文件的函数

void saveData(){
    FILE *fptr = fopen("Manager_Data.txt", "w");
    for (int i = 0;i < TAM_EMP; i++) {
        fprintf(fptr, "%d,%s,%s,%d,%s,%s,%s,%d
", employees[i].ID, employees[i].name, employees[i].date, employees[i].phone, employees[i].email, employees[i].local, employees[i].depart, employees[i].availability);
    }
    fclose(fptr);
}

问题分析与修复方案

1. GetData函数失效的原因及修复

  • 未处理文件打开失败:若文件不存在或无读取权限,fopen返回NULL,直接调用fscanf会触发程序崩溃,必须先校验文件指针有效性。
  • 格式字符串匹配错误:原代码用%s读取字段,会在空白字符处停止读取,若字段包含空格会导致数据截断;同时格式串中的换行符匹配逻辑不稳定,易引发读取错位。
  • 未校验读取结果:无法确认每行8个字段是否全部读取成功,可能出现部分数据加载失败的情况。

修复后的GetData函数:

void GetData(){
    FILE *fptr = fopen("Manager_Data.txt", "r");
    if (fptr == NULL) {
        // 文件不存在时初始化空结构体,避免后续保存垃圾数据
        for (int i = 0; i < TAM_EMP; i++) {
            employees[i].ID = 0;
            employees[i].phone = 0;
            employees[i].availability = 0;
            // 初始化字符串字段为空
            memset(employees[i].name, 0, sizeof(employees[i].name));
            memset(employees[i].date, 0, sizeof(employees[i].date));
            memset(employees[i].email, 0, sizeof(employees[i].email));
            memset(employees[i].local, 0, sizeof(employees[i].local));
            memset(employees[i].depart, 0, sizeof(employees[i].depart));
        }
        return;
    }

    int i = 0;
    // 逐行读取直到文件结束或达到最大员工数,校验读取字段数
    while (i < TAM_EMP && fscanf(fptr, "%d,%[^,],%[^,],%d,%[^,],%[^,],%[^,],%d
", 
                                &employees[i].ID, employees[i].name, employees[i].date, 
                                &employees[i].phone, employees[i].email, employees[i].local, 
                                employees[i].depart, &employees[i].availability) == 8) {
        i++;
    }

    // 剩余未读取的位置初始化为空
    for (; i < TAM_EMP; i++) {
        employees[i].ID = 0;
        employees[i].phone = 0;
        employees[i].availability = 0;
        memset(employees[i].name, 0, sizeof(employees[i].name));
        memset(employees[i].date, 0, sizeof(employees[i].date));
        memset(employees[i].email, 0, sizeof(employees[i].email));
        memset(employees[i].local, 0, sizeof(employees[i].local));
        memset(employees[i].depart, 0, sizeof(employees[i].depart));
    }

    fclose(fptr);
}

说明:

  • 新增文件打开失败的判断逻辑,初始化空结构体避免垃圾数据流入。
  • 用%[^,]替代%s,确保完整读取逗号分隔的字段(前提是字段本身不含逗号)。
  • 循环读取时校验fscanf返回值,确保每次成功读取8个字段。

2. 保存时不覆盖原有内容的问题及修复

当前saveData用"w"模式打开文件,该模式会清空文件再写入,出现不覆盖的情况大概率是文件打开失败未处理:若fopen返回NULL,后续fprintf不会执行,原有内容自然保留。

修复后的saveData函数:

void saveData(){
    FILE *fptr = fopen("Manager_Data.txt", "w");
    if (fptr == NULL) {
        // 可添加错误提示,比如printf("无法保存文件!
");
        return;
    }

    for (int i = 0; i < TAM_EMP; i++) {
        // 只保存ID不为0的有效员工数据,避免写入空数据
        if (employees[i].ID != 0) {
            fprintf(fptr, "%d,%s,%s,%d,%s,%s,%s,%d
", 
                    employees[i].ID, employees[i].name, employees[i].date, 
                    employees[i].phone, employees[i].email, employees[i].local, 
                    employees[i].depart, employees[i].availability);
        }
    }

    fclose(fptr);
}

说明:

  • 新增文件打开失败的判断,避免无意义操作。
  • 仅保存ID不为0的有效员工数据,减少文件中的无效内容。

额外建议

  • 定义结构体时,确保字符串字段有足够长度,避免缓冲区溢出。
  • 可考虑使用二进制文件读写(fread/fwrite),比文本格式更可靠,尤其适合结构体数据。
  • 程序启动时必须调用GetData,退出时调用saveData,确保数据加载和保存时机正确。

内容的提问来源于stack exchange,提问作者Antônio Velez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:50:32