二进制文件中基于员工编号的顺序查找功能故障排查求助
二进制文件员工记录顺序查找问题修复
核心错误分析
- 查找函数的文件定位错误:
sequencial_search中每次循环都用fseek(file, sizeof(struct Employee), SEEK_SET)把文件指针重置到开头,导致永远只读取第一条记录,无法遍历后续条目。 - 文件打开方式错误:main函数用
wb+打开文件,该模式会清空原有文件内容并创建新文件,导致文件中没有预存的100条记录可查。 - read函数的潜在问题:
- malloc时的类型转换冗余(C语言中无需强制转换
void*) - 仅检查了
code的读取结果,未校验其他字段的fread返回值,可能导致部分读取失败后出现非法数据 - 字符数组(name、cpf等)读取后未添加字符串终止符
\0,printf输出时会出现乱码或未定义行为
- malloc时的类型转换冗余(C语言中无需强制转换
- 查找循环未处理文件提前结束的情况:如果文件中记录不足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
相关产品推荐
相关产品推荐

