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

二进制文件中基于员工编号的顺序查找功能故障排查求助

二进制文件员工记录顺序查找问题修复

核心错误分析

  1. 查找函数的文件定位错误:sequencial_search中每次循环都用fseek(file, sizeof(struct Employee), SEEK_SET)把文件指针重置到开头,导致永远只读取第一条记录,无法遍历后续条目。
  2. 文件打开方式错误:main函数用wb+打开文件,该模式会清空原有文件内容并创建新文件,导致文件中没有预存的100条记录可查。
  3. read函数的潜在问题:
    • malloc时的类型转换冗余(C语言中无需强制转换void*)
    • 仅检查了code的读取结果,未校验其他字段的fread返回值,可能导致部分读取失败后出现非法数据
    • 字符数组(name、cpf等)读取后未添加字符串终止符\0,printf输出时会出现乱码或未定义行为
  4. 查找循环未处理文件提前结束的情况:如果文件中记录不足100条,read会返回NULL,此时直接访问emp->code会触发空指针异常。

修复后的代码

结构体定义(无修改)

typedef struct Employee {
    int code;
    char name[30];
    char cpf[11];
    char birthday[11];
    double wage;
} TEmployee;

修复后的read函数

TEmployee *read(FILE *in) {
    TEmployee *emp = malloc(sizeof(TEmployee));
    if (!emp) {
        return NULL; // 内存分配失败
    }

    // 逐个校验所有字段的读取结果
    if (fread(&emp->code, sizeof(int), 1, in) != 1 ||
        fread(emp->name, sizeof(char), sizeof(emp->name)-1, in) != sizeof(emp->name)-1 ||
        fread(emp->cpf, sizeof(char), sizeof(emp->cpf)-1, in) != sizeof(emp->cpf)-1 ||
        fread(emp->birthday, sizeof(char), sizeof(emp->birthday)-1, in) != sizeof(emp->birthday)-1 ||
        fread(&emp->wage, sizeof(double), 1, in) != 1) {
        free(emp);
        return NULL;
    }

    // 手动添加字符串终止符,避免printf乱码
    emp->name[sizeof(emp->name)-1] = '\0';
    emp->cpf[sizeof(emp->cpf)-1] = '\0';
    emp->birthday[sizeof(emp->birthday)-1] = '\0';

    return emp;
}

修复后的sequencial_search函数

TEmployee *sequencial_search(int code, FILE *file) {
    // 先把文件指针重置到开头,避免之前的操作影响
    fseek(file, 0, SEEK_SET);
    int i = 0;
    while (i < 100) {
        // 计算第i条记录的偏移量:i * 结构体大小
        fseek(file, i * sizeof(TEmployee), SEEK_SET);
        TEmployee *emp = read(file);
        if (!emp) {
            break; // 文件提前结束,退出循环
        }
        if (code == emp->code) {
            return emp;
        }
        free(emp); // 未找到则释放内存,避免泄漏
        i++;
    }   
    return NULL;
}

修复后的main函数

int main() {
    // 使用rb模式打开文件(只读二进制),避免清空原有数据
    FILE *file = fopen("prova1.dat", "rb");
    if (!file) {
        printf("无法打开文件!\n");
        return 1;
    }

    TEmployee *emp = sequencial_search(8, file);
    if (emp != NULL) {
        printf("### 找到员工记录! ### \n");
        printf("编号: %d \n", emp->code);
        printf("姓名: %s \n", emp->name);
        printf("CPF: %s \n", emp->cpf);
        printf("生日: %s \n", emp->birthday);
        printf("薪资: %.2f \n", emp->wage);
        free(emp);
    } else {
        printf("未找到指定员工记录! \n");
    }

    fclose(file);
    return 0;
}

额外注意事项

  • 确保prova1.dat文件确实存在且包含100条完整的TEmployee结构体记录,记录的写入格式需与读取格式一致(即写入时用fwrite完整写入结构体)。
  • 若需要读写文件,可改用rb+模式,但不要用wb+或w类模式,避免清空数据。

内容的提问来源于stack exchange,提问作者Cláudio Vitor Dantas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:48:21