C语言二进制文件重写结构体更新车辆信息失败问题排查
二进制文件车辆记录更新失败原因排查
你写的updateCarro()函数存在多类问题,从编译错误到核心逻辑错误都有,直接导致覆盖操作失效,具体问题点如下:
- 基础语法与变量拼写错误
- 声明的局部变量为循环计数
cont、总记录数regs,循环代码里错写为cout/count/records,变量名不匹配会直接导致编译失败,循环逻辑根本无法执行 scanf(" %d", &carro.ar)行末尾缺失分号,属于基础语法错误- 打开文件后全程没有调用
fclose(fp)关闭文件,写入操作的内容会滞留在IO缓冲区,不会实际刷写到磁盘文件中 - 缺失
fopen返回值校验,如果文件打开失败拿到NULL指针,后续所有文件操作都会触发内存错误
- 声明的局部变量为循环计数
- 核心写入逻辑错误(就算编译通过也无法正确更新)
- 文件指针位置错误:
fread读取完匹配ID的记录后,文件指针会自动向后偏移一个sizeof(Carros)的长度,停在当前记录的末尾、下一条记录的起始位置。这时候直接调用fwrite,会把新数据写到下一条记录的位置,覆盖无关数据,根本不会改写你要更新的目标旧记录。查询函数mostraCarro()只需要读数据不需要写,所以不需要处理指针回退,但写入场景必须在写之前把指针移回当前记录的起始位置。 - 新录入数据被读取操作覆盖:你提前把用户输入的新车辆信息存在
carro结构体变量中,但循环遍历文件时,每次fread都会把文件中读出的旧记录直接写入carro变量,提前录入的新数据会被完全冲掉。等匹配到目标ID时,carro里存的已经是从文件读出来的旧数据,就算执行写入也是把旧数据原封不动写回去,不会产生任何更新效果。
- 文件指针位置错误:
修正后的参考实现
void updateCarro() { FILE *fp = fopen("Carros.dat", "rb+"); // 新增文件打开校验 if (fp == NULL) { printf("Erro ao abrir o arquivo\n"); return; } Carros carro, novo_carro; // 分开存新录入数据和文件读出的旧数据 int id, size, count, regs; printf("Entre com o ID do carro a ser atualizado: \n"); scanf("%d", &id); // 待更新的车辆ID // 读取新的车辆信息,存在独立的novo_carro变量里,避免被fread覆盖 printf("Entre com os novos dados do carro: \n"); scanf(" %d", &novo_carro.id); scanf(" %s", novo_carro.placa); scanf(" %s", novo_carro.modelo); scanf(" %f", &novo_carro.motor); scanf(" %d", &novo_carro.ar); // 补全缺失的分号 scanf(" %s", novo_carro.cor); scanf(" %d", &novo_carro.ano); scanf(" %d", &novo_carro.kilo); scanf(" %f", &novo_carro.diaria); scanf(" %d", &novo_carro.dispo); if(fseek(fp, 0, SEEK_END) == -1) { printf("Erro ao localizar o registro\n"); fclose(fp); return; } size = ftell(fp); if(size == -1 || size == 0) { printf("Não há registros\n"); fclose(fp); return; } if(fseek(fp, 0, SEEK_SET) == -1) { printf("Erro ao localizar o registro\n"); fclose(fp); return; } // 统一变量名,修正拼写错误 regs = size / sizeof(Carros); for(count = 0; count < regs; count++) { long pos = ftell(fp); // 先记录当前记录的起始位置 fread(&carro, sizeof(Carros), 1, fp); if(carro.id == id) { // 把文件指针回退到当前记录的起始位置,再写入新数据 fseek(fp, pos, SEEK_SET); fwrite(&novo_carro, sizeof(Carros), 1, fp); printf("Registro atualizado com sucesso\n"); break; } } // 操作完成后关闭文件,强制刷写缓冲区数据到磁盘 fclose(fp); }
注意:二进制文件按固定长度结构体读写时,只要写入数据长度和结构体长度完全一致,就可以通过偏移指针直接覆盖对应位置的记录,不需要重写整个文件。
内容的提问来源于stack exchange,提问作者Raphael Ozono
相关产品推荐
相关产品推荐

