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

二进制文件读写C语言代码问题:汽车数据读写后值异常

问题修复方案:二进制文件读写汽车数据异常

核心问题分析

  1. 读写逻辑完全不匹配:写入时拆分字段、根据发动机类型选择性写入不同数据,但读取时直接按完整car结构体读取,文件字节流与结构体内存布局完全错位,导致所有字段解析混乱。
  2. 写入函数参数错误:写入engine和make时,错误使用sizeof(car)作为写入长度,实际应使用对应枚举类型的大小(sizeof(engine_Type)、sizeof(car_Make)),额外写入的无效字节彻底打乱了文件结构。
  3. 随机数种子初始化时机错误:srand在生成汽车数据之后调用,导致每次生成的随机数序列固定,失去随机性。
  4. 未初始化字段:结构体部分字段未初始化,写入文件时会带入垃圾数据,影响读取结果。

修复步骤

  • 统一读写逻辑:采用完整写入/读取整个结构体的方式,避免选择性写入的复杂度,确保文件字节流与结构体内存布局完全对应。
  • 修正写入参数错误:通过完整读写结构体直接规避字段写入长度错误问题。
  • 调整随机数种子时机:将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:12:06