二进制文件读写C语言代码问题:汽车数据读写后值异常
问题修复方案:二进制文件读写汽车数据异常
核心问题分析
- 读写逻辑完全不匹配:写入时拆分字段、根据发动机类型选择性写入不同数据,但读取时直接按完整
car结构体读取,文件字节流与结构体内存布局完全错位,导致所有字段解析混乱。 - 写入函数参数错误:写入
engine和make时,错误使用sizeof(car)作为写入长度,实际应使用对应枚举类型的大小(sizeof(engine_Type)、sizeof(car_Make)),额外写入的无效字节彻底打乱了文件结构。 - 随机数种子初始化时机错误:
srand在生成汽车数据之后调用,导致每次生成的随机数序列固定,失去随机性。 - 未初始化字段:结构体部分字段未初始化,写入文件时会带入垃圾数据,影响读取结果。
修复步骤
- 统一读写逻辑:采用完整写入/读取整个结构体的方式,避免选择性写入的复杂度,确保文件字节流与结构体内存布局完全对应。
- 修正写入参数错误:通过完整读写结构体直接规避字段写入长度错误问题。
- 调整随机数种子时机:将
srand放在生成数据之前,保证随机数序列真正随机。 - 初始化结构体字段:生成汽车数据时初始化所有字段,避免垃圾数据写入文件。
- 完善错误处理:补充文件操作的错误检查,明确提示并在失败时终止程序。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <process.h> typedef enum { hybrid, ICE, electric } engine_Type; typedef enum { tesla, bmw, toyota, mercedes_benz, hyundai, volkswagen, nissan } car_Make; typedef union { int electricEffInt; float iceEffFloat; } efficiency; // 修正原拼写错误effincy typedef struct { engine_Type engine; car_Make make; int hybridEffInt; float hybridEffFloat; efficiency carEfficiency; int maximumTorque; } car; // Mix is used for seed generation unsigned long mix(unsigned long a, unsigned long b, unsigned long c) { a=a-b; a=a-c; a=a^(c >> 13); b=b-c; b=b-a; b=b^(a << 8); c=c-a; c=c-b; c=c^(b >> 13); a=a-b; a=a-c; a=a^(c >> 12); b=b-c; b=b-a; b=b^(a << 16); c=c-a; c=c-b; c=c^(b >> 5); a=a-b; a=a-c; a=a^(c >> 3); b=b-c; b=b-a; b=b^(a << 10); c=c-a; c=c-b; c=c^(b >> 15); return c; } car carGeneration() { car car; car.engine = rand() % 3; car.make = rand() % 7; // 优化扭矩计算,避免整数除法导致的结果错误 car.maximumTorque = 250 + (rand() % (3800 - 250 + 1)); // 初始化所有字段,避免垃圾数据写入文件 car.hybridEffInt = 0; car.hybridEffFloat = 0.0f; car.carEfficiency.electricEffInt = 0; car.carEfficiency.iceEffFloat = 0.0f; switch (car.engine) { case hybrid: car.hybridEffInt = 12 + (rand() % (18 - 12 + 1)); car.hybridEffFloat = 3.3f + ((float)rand() / RAND_MAX) * (8.5f - 3.3f); break; case ICE: car.carEfficiency.iceEffFloat = 3.3f + ((float)rand() / RAND_MAX) * (8.5f - 3.3f); break; case electric: car.carEfficiency.electricEffInt = 12 + (rand() % (18 - 12 + 1)); break; } return car; } void multipleCarGeneration(int carCount, car *cars){ // 修正拼写错误mulipleCarGeneartion for(int i = 0; i < carCount ; i++){ cars[i] = carGeneration(); } } void write_file(car *cars, int amount){ FILE* out = fopen("cars.dat", "wb"); if(out == NULL){ printf("无法创建文件,程序退出\n"); exit(EXIT_FAILURE); } // 直接写入整个结构体数组,保证数据结构一致 size_t written = fwrite(cars, sizeof(car), amount, out); if(written != amount){ printf("写入文件时出错,仅写入%d辆汽车数据\n", (int)written); } fclose(out); } void read_file(car *cars, int amount) { int teslaCount = 0, bmwCount=0, toyotaCount=0, mercedes_BenzCount=0, hyundaiCount=0, volkswagenCount=0, nissanCount=0; FILE *in = fopen("cars.dat", "rb"); if (in == NULL) { printf("无法读取文件,程序退出\n"); exit(EXIT_FAILURE); } size_t read = fread(cars, sizeof(car), amount, in); if(read != amount){ printf("读取文件时出错,仅读取%d辆汽车数据\n", (int)read); amount = (int)read; } printf("汽车品牌统计(数量):\n"); printf("Tesla BMW Toyota Mercedes-Benz Volkswagen Nissan\n"); for (int j = 0; j < 60; j++) { printf("-"); } printf("\n"); for (int i = 0; i < amount; i++) { printf("发动机类型:%d\n", cars[i].engine); printf("汽车品牌:%d\n", cars[i].make); printf("最大扭矩:%d\n", cars[i].maximumTorque); switch (cars[i].make) { case tesla: teslaCount++; break; case bmw: bmwCount++; break; case toyota: toyotaCount++; break; case mercedes_benz: mercedes_BenzCount++; break; case hyundai: hyundaiCount++; break; case volkswagen: volkswagenCount++; break; case nissan: nissanCount++; break; } switch (cars[i].engine) { case hybrid: printf("混动效率(整数):%d\n", cars[i].hybridEffInt); printf("混动效率(浮点):%.2f\n", cars[i].hybridEffFloat); break; case ICE: printf("燃油效率:%.2f\n", cars[i].carEfficiency.iceEffFloat); break; case electric: printf("电动效率:%d\n", cars[i].carEfficiency.electricEffInt); break; } printf("---\n"); } printf("统计结果:Tesla:%d BMW:%d Toyota:%d Mercedes-Benz:%d Volkswagen:%d Nissan:%d\n", teslaCount, bmwCount, toyotaCount, mercedes_BenzCount, volkswagenCount, nissanCount); fclose(in); } int main() { int generationAmount = 20; car carsArray[generationAmount]; // 先初始化随机数种子,再生成数据 srand(mix(clock(), time(NULL), getpid())); multipleCarGeneration(generationAmount, carsArray); write_file(carsArray, generationAmount); read_file(carsArray, generationAmount); return 0; }
额外说明
- 修正了原代码中的拼写错误(
effincy→efficiency,mulipleCarGeneartion→multipleCarGeneration)。 - 优化了效率和扭矩的计算方式,避免整数除法导致的精度丢失。
- 完善了统计结果的输出格式,可读性更强。
内容的提问来源于stack exchange,提问作者Daniel Boos
相关产品推荐
相关产品推荐

