整个目标是创建具有以下属性的生成1000辆汽车,将它们写入二进制文件,从该二进制文件中读取它们并对它们进行计数.请注意,如果汽车是混合动力车,那么它将有两个效率,一个是浮点型,另一个是整型.下面的代码是因为我在上面花了太多的时间(现在已经两天了).

#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;
} effincy;

typedef struct {
    engine_Type engine;
    car_Make make;
    int hybridEffInt;
    float hybridEffFloat;
    effincy 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()/(RAND_MAX/(3800-250)));

    switch (car.engine) {
        case hybrid: car.hybridEffInt = (12 + rand() / (RAND_MAX / (18 - 12)));
        car.hybridEffFloat = (float)(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() / (RAND_MAX / (18 - 12)));
            break;
    }

    return car;
}

void mulipleCarGeneartion(int carCount, car *cars){
    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("File does not exist creating file");
    }

    for (int i=0;i< amount ;i++) {
        //fwrite(&cars[i], sizeof(car) , 1,out);
        fwrite(&cars[i].engine, sizeof(car) , 1,out);
        fwrite(&cars[i].make, sizeof(car) , 1,out);
        fwrite(&cars[i].maximumTorque, sizeof(int) , 1,out);

        switch (cars[i].engine) {
            case hybrid: fwrite(&cars[i].hybridEffInt, sizeof(int) , 1,out);
                fwrite(&cars[i].hybridEffFloat, sizeof(float) , 1,out);
                break;
            case ICE:
                fwrite(&cars[i].carEfficiency.iceEffFloat, sizeof(float) , 1,out);
                break;
            case electric:fwrite(&cars[i].carEfficiency.electricEffInt, sizeof(int) , 1,out);
                break;
        }

    }
    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("Can not read file");
    }

    printf("Car makes (Quantity): \n");
    printf("Tesla BMW Toyota Mercedes-Benz Volkswagen Nissan\n");

    for (int j = 0; j<50; j++) {
        printf("-");
    }

    printf("\n");

    for (int i = 0; i < amount; i++) {
        fread(&cars[i],sizeof(car), 1, in);
        printf("engine Type: %d \n", cars[i].engine);
        printf("car Make: %d \n", cars[i].make);
        printf("Torque %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("hybrid efficiencyINT: %d\n", cars[i].hybridEffInt);
                printf("hybrid efficiencyFLOAT: %f\n", cars[i].hybridEffFloat);
                break;
            case ICE:
                printf("ICE efficiency: %f\n", cars[i].carEfficiency.iceEffFloat);
                break;
            case electric:
                printf("electric efficiency: %d\n", cars[i].carEfficiency.electricEffInt);
        }
    }
    printf("Count bob %d %d %d %d %d %d", bmwCount, hyundaiCount,volkswagenCount,nissanCount, teslaCount, toyotaCount);

}

int main() {
    int generationAmount = 20;
    car carsArray[generationAmount];
    mulipleCarGeneartion(generationAmount, carsArray);
    srand(mix(clock(), time(NULL), getpid()));
    write_file(carsArray, generationAmount);
    read_file(carsArray,generationAmount);
    return 0;
}

我首先调试并找到存储在数组中的值.现在问题似乎出在WRITE函数或READ函数上.我以为做fwrite(&cars[i].engine, sizeof(car) , 1,out));会写下有关数组的所有内容,包括属性,但老实说,我不确定,因此我try 让多个fwrite来写有关Car的所有内容,并在读取文件时以相同的顺序读取它们.我试着更改FWRITE内部的SIZOF,但都不起作用.

This is the current output:

engine Type: 2
car Make: 1
Torque 953
electric efficiency: 16
engine Type: 1
car Make: 1363987785
Torque 2
ICE efficiency: 0.000000
engine Type: 953
car Make: 16 
Torque 32760 
engine Type: 17 
car Make: 1525 
Torque 17 
engine Type: 1525 
car Make: 1 
Torque 6 
Count bob 2 0 0 0 0 0

这是不正确的,汽车的范围是0-7,发动机类型是0-3,扭矩的最小值是250.使这个问题变得更难的是,我无法查看二进制文件并理解数据来查看问题所在.我知道我可以将它转换为十六进制,但我要用十六进制做什么?

推荐答案

  1. 首先,我通过使用变量而不是将类型名设置为sizeof(),修复了明显的类型混淆:
        fwrite(&cars[i].engine, sizeof(car) , 1,out);
        fwrite(&cars[i].make, sizeof(car) , 1,out);

为了调试这个问题,我随后编写了一个cars_print()函数,禁用了read_file()中的打印(这是混合问题),注释掉了srand(),并将看起来很好的generationAmount减少到1,然后将2减少到2,从而产生了差异:

#define generationAmount 2

void print_cars(int amount, car cars[amount]) {
    for(size_t i = 0; i < generationAmount; i++) {
        printf("i = %zu\n", i);
        printf(
            "engine: %d\n"
            "make: %d\n",
            cars[i].engine,
            cars[i].make
        );
        switch (cars[i].engine) {
            case hybrid:
                printf("hybridEffInt: %d\n"
                    "hybridEffFloat: %f\n",
                    cars[i].hybridEffInt,
                    cars[i].hybridEffFloat
                );
            case ICE:
                printf("carEfficiency.iceEffFloat: %f\n", cars[i].carEfficiency.iceEffFloat);
                break;
            case electric:
                printf("carEfficiency.electricEffInt: %d\n", cars[i].carEfficiency.electricEffInt);
                break;

        }
        printf("maximumTorque: %d\n", cars[i].maximumTorque);
    }
}

int main() {
    car carsArray[generationAmount];
    //srand(mix(clock(), time(NULL), getpid()));
    mulipleCarGeneartion(generationAmount, carsArray);
    print_cars(generationAmount, carsArray);
    write_file(generationAmount, carsArray);
    read_file(generationAmount, carsArray);
    print_cars(generationAmount, carsArray);
}

它产生的输出是:

i = 0
engine: 1
make: 4
carEfficiency.iceEffFloat: 7.451888
maximumTorque: 3030
i = 1
engine: 2
make: 3
carEfficiency.electricEffInt: 16
maximumTorque: 1440
i = 0
engine: 1
make: 4
carEfficiency.iceEffFloat: 0.000000
maximumTorque: 3
i = 1
engine: 1440
make: 16
maximumTorque: 1440
  1. 然后我查看了write_file()read_file(),并特别注意上面输出的carEfficiency.iceEffFloat,这是有问题的.我发现您会根据值engine写出单独的字段,特别是carEfficiencyhybridEffInthybridEffFloat,但在read_file()中,您读取的是不同的car struct .简单的解决方法是一次性写入和读取整个数组:
void write_file(int amount, car cars[amount]){
    FILE *out = fopen("cars.dat", "wb");
    if(!out) {
        printf("File does not exist creating file");
        return;
    }
    fwrite(cars, sizeof *cars, amount, out);
    fclose(out);
}

void read_file(int amount, car cars[amount]) {
    FILE *in = fopen("cars.dat", "rb");
    if (!in) {
        printf("Can not read file");
        return;
    }
    fread(cars, sizeof *cars, amount, in);
    fclose(in);

}

您应该判断fread()fwrite()的返回值.使用不同的数组来写入数据而不是读取数据也是一个好主意,这样就不会出现任何意外情况.这将为electricice写出一个未使用的变量,但对于更干净的代码来说,这可能是值得的.如果您不想这样做,则必须单独读写字段.

  1. 您编写的顺序也与您的 struct 成员的顺序不同.maximumTorque写在make之后,但在 struct 中它在carEfficiency之后.

  2. 这其中存在数据建模问题.efficiency是一个并集,但你在cars中有hybridEffFloathybridEffInt.最简单的解决方法是在3种引擎类型中使用相同的变量名,这意味着您可以省go (并集)efficiency,只在cars中使用这两个字段,因为您不会在其他地方使用它:

typedef struct {
    engine_Type engine;
    car_Make make;
    int efficiency_electric;
    float efficiency_ice;
    int maximumTorque;
} car;
  1. 不要在变量名中编码类型.如果您需要更改类型,这意味着您还必须更改变量名以避免混淆(DRY).

  2. 最后,重新实现read_file()中的制表逻辑.我注意到我的两张唱片的数字是1.这是因为您没有打印出所有变量(mercedes_BenzCount).请改用数组:

void tabulate_cars(int amount, car cars[amount]) {
    printf("Car makes (Quantity): \n");
    printf("Tesla BMW Toyota Mercedes-Benz Volkswagen Nissan\n");

    int counts[make_count] = { 0 };
    for (int j = 0; j<50; j++)
        printf("-");
    printf("\n");
    for(size_t i = 0; i < amount; i++)
        counts[cars[i].make]++;
    printf("Count bob ");
    for(size_t i = 0; i < make_count; i++)
        printf("%d%s", counts[i], i + 1 < make_count ? " " : "\n");
}

请注意,输出略有不同,您现在有两个函数来打印详细信息和提交数据.在Tablate中,您仍然硬编码标签以匹配枚举顺序.解决这个问题的方法是X宏,顺便说一句,但答案已经变得相当长了.

  1. 这是一个小问题,但更喜欢数组之前的数组长度参数,这样您就可以记录它们是如何相关的.

  2. go 掉carGeneration个,只用mulipleCarGeneartion()个,这样就能与其他函数保持一致.前者是后者的特例,所以你不需要它.为保持一致性,还将其重命名为generate_cars().

  3. srand()应该出现在rand()之前才有效果(即generate_cars()之前).

以下是全部内容:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define generationAmount 20

typedef enum {
    hybrid, ICE, electric
} engine_Type;

typedef enum {
    tesla, bmw, toyota, mercedes_benz, hyundai, volkswagen, nissan, make_count
} car_Make;

typedef struct {
    engine_Type engine;
    car_Make make;
    int efficiency_electric;
    float efficiency_ice;
    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;
}

void print_cars(int amount, car cars[amount]) {
    for(size_t i = 0; i < generationAmount; i++) {
        printf("i = %zu\n", i);
        printf(
            "engine: %d\n"
            "make: %d\n",
            cars[i].engine,
            cars[i].make
        );
        switch (cars[i].engine) {
            case hybrid:
                printf("efficientcy_eletric: %d\n", cars[i].efficiency_electric);
                printf("efficientcy_ice: %f\n", cars[i].efficiency_ice);
            case electric:
                printf("efficientcy_eletric: %d\n", cars[i].efficiency_electric);
                break;
            case ICE:
                printf("efficientcy_ice: %f\n", cars[i].efficiency_ice);
                break;

        }
        printf("maximumTorque: %d\n\n", cars[i].maximumTorque);
    }
}

void generate_cars(int carCount, car cars[carCount]){
    for(int i =0;i < carCount ;i++) {
        cars[i].engine = rand()%3;
        cars[i].make = rand()%7;
        cars[i].maximumTorque = (250 + rand()/(RAND_MAX/(3800-250)));
        switch (cars[i].engine) {
            case hybrid:
                cars[i].efficiency_electric = (12 + rand() / (RAND_MAX / (18 - 12)));
                cars[i].efficiency_ice = (3.3f + rand() / ((float) RAND_MAX / (8.5f - 3.3f)));
                break;
            case ICE:
                cars[i].efficiency_ice = (3.3f + rand() / ((float) RAND_MAX / (8.5f - 3.3f)));
                break;
            case electric:
                cars[i].efficiency_electric = (12 + rand() / (RAND_MAX / (18 - 12)));
                break;
        }
    }
}

void write_file(int amount, car cars[amount]){
    FILE *out = fopen("cars.dat", "wb");
    if(!out) {
        printf("File does not exist creating file");
        return;
    }
    fwrite(cars, sizeof *cars, amount, out);
    fclose(out);
}

void read_file(int amount, car cars[amount]) {
    FILE *in = fopen("cars.dat", "rb");
    if (!in) {
        printf("Can not read file");
        return;
    }
    fread(cars, sizeof *cars, amount, in);
    fclose(in);

}

void tabulate_cars(int amount, car cars[amount]) {
    printf("Car makes (Quantity): \n");
    printf("Tesla BMW Toyota Mercedes-Benz Volkswagen Nissan\n");

    int counts[make_count] = { 0 };
    for (int j = 0; j<50; j++)
        printf("-");
    printf("\n");
    for(size_t i = 0; i < amount; i++)
        counts[cars[i].make]++;
    printf("Count bob ");
    for(size_t i = 0; i < make_count; i++)
        printf("%d%s", counts[i], i + 1 < make_count ? " " : "\n");
}

int main() {
    car cars[generationAmount];
    srand(mix(clock(), time(NULL), getpid()));
    generate_cars(generationAmount, cars);
    //print_cars(generationAmount, carsArray);
    write_file(generationAmount, cars);
    read_file(generationAmount, cars);
    print_cars(generationAmount, cars);
    tabulate_cars(generationAmount, cars);
}

以及产生的输出:

i = 0
engine: 2
make: 6
efficientcy_eletric: 16
maximumTorque: 2850

i = 1
engine: 0
make: 2
efficientcy_eletric: 16
efficientcy_ice: 4.687404
efficientcy_eletric: 16
maximumTorque: 2232

i = 2
engine: 2
make: 3
efficientcy_eletric: 15
maximumTorque: 1824

i = 3
engine: 1
make: 1
efficientcy_ice: 3.948720
maximumTorque: 2400

i = 4
engine: 0
make: 3
efficientcy_eletric: 12
efficientcy_ice: 6.890365
efficientcy_eletric: 12
maximumTorque: 2543

i = 5
engine: 0
make: 0
efficientcy_eletric: 15
efficientcy_ice: 6.773261
efficientcy_eletric: 15
maximumTorque: 2722

i = 6
engine: 2
make: 2
efficientcy_eletric: 17
maximumTorque: 282

i = 7
engine: 2
make: 3
efficientcy_eletric: 14
maximumTorque: 2845

i = 8
engine: 0
make: 4
efficientcy_eletric: 13
efficientcy_ice: 4.352170
efficientcy_eletric: 13
maximumTorque: 261

i = 9
engine: 0
make: 0
efficientcy_eletric: 14
efficientcy_ice: 6.686623
efficientcy_eletric: 14
maximumTorque: 2542

i = 10
engine: 1
make: 3
efficientcy_ice: 7.677234
maximumTorque: 3004

i = 11
engine: 2
make: 2
efficientcy_eletric: 12
maximumTorque: 3486

i = 12
engine: 1
make: 1
efficientcy_ice: 6.545116
maximumTorque: 3264

i = 13
engine: 0
make: 2
efficientcy_eletric: 16
efficientcy_ice: 4.487165
efficientcy_eletric: 16
maximumTorque: 3457

i = 14
engine: 1
make: 4
efficientcy_ice: 3.627770
maximumTorque: 3655

i = 15
engine: 2
make: 2
efficientcy_eletric: 16
maximumTorque: 485

i = 16
engine: 0
make: 1
efficientcy_eletric: 16
efficientcy_ice: 4.707179
efficientcy_eletric: 16
maximumTorque: 1418

i = 17
engine: 0
make: 2
efficientcy_eletric: 16
efficientcy_ice: 4.103405
efficientcy_eletric: 16
maximumTorque: 1081

i = 18
engine: 2
make: 3
efficientcy_eletric: 17
maximumTorque: 485

i = 19
engine: 1
make: 5
efficientcy_ice: 7.746961
maximumTorque: 2728

Car makes (Quantity):
Tesla BMW Toyota Mercedes-Benz Volkswagen Nissan
--------------------------------------------------
Count bob 2 3 6 5 2 1 1

C++相关问答推荐

使用SWI—Prolog的qsave_program生成二进制文件有什么好处?'

丑陋的三重间接:可扩展的缓冲区管理 struct

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

如何将字符串传递给函数并返回在C中更改的相同字符串?

模拟shell并运行.sh文件

非正规化边缘毛刺

Sizeof(&Q;字符串&Q;)的正确输出是什么?

在Rust和C之间使用ffi时如何通过 struct 中的[U8;1]成员传递指针

理解C版宏(看起来像未声明的变量?)

防止C++中递归函数使用堆栈内存

getline()从c中的外部函数传递指针时输出null

如何将另一个数组添加到集合中,特别是字符串?

在C语言中,指针指向一个数组

正数之和是负数

递归打印二维数组(C编程)

如果格式字符串的内存与printf的一个参数共享,会发生什么情况?

哪个首选包含第三个库S头文件?#INCLUDE;文件名或#INCLUDE<;文件名&>?

gdb - 你能找到持有内部 glibc 锁的线程吗?

如何向 execl 创建的后台程序提供输入?

无法在 C 中打开文本文件,我想从中读取文本作为数据并将其写入数组