C 结构数据在迭代循环外无法保持一致

C struct data failing to be consistent outside iterative loop

我有一个程序,我希望使用 fscanf 将汽车数据读入 for 循环中的结构数组(我知道,我应该使用 fgets 或其他东西,但它是这个 assinment 所必需的)和按平均 MPG 对数据进行排序,并使用 fprintf 将排序后的数据输出到新文件。当我读取数据时,在主函数的 for 循环中,作为调试功能,我打印分配给 struct[i] 的所有数据,然后继续到包含后续数据的文本文件中的下一行结构对象。但是,在输入完所有数据并且到目前为止一切正常之后,我重新打印结构数组中的所有信息,并且前两个数据区域 "make" 和 "model" 都带上了字符串分配的最后一个结构。我已经修复了几个小时的错误,但没有找到解决方案。谁能告诉我我的代码做错了什么? 提前谢谢大家!

// Written by 4ur0r4
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Car {
    char *make;
    char *model;
    int year;
    int city_mpg;
    int highway_mpg;
};

int averagempg(struct Car car) {
    return (car.city_mpg + car.highway_mpg) / 2;
}

void selection_sort(struct Car *cars, int n) {
    struct Car temp;
    int i;
    for (i = 0; i < n - 1; i++) {
        if (averagempg(cars[i]) > averagempg(cars[i + 1])) {
            temp = cars[i];
            cars[i] = cars[i + 1];
            cars[i + 1] = temp;
        }
    }
}

void write_cars(struct Car *cars, int n) {
    FILE *output = fopen("sorted_cars.txt", "w");
    int i;
    for (i = 0; i < n; i++) {
        fprintf(output, "%s ", cars[i].make);
        fprintf(output, "%s ", cars[i].model);
        fprintf(output, "%d ", cars[i].year);
        fprintf(output, "%d ", cars[i].city_mpg);
        fprintf(output, "%d\n", cars[i].highway_mpg);
    }
}

void print_cars(struct Car *cars, int n) {
    int i;
    for (i = 0; i < n; i++) {
        printf("%s ", cars[i].make);
        printf("%s ", cars[i].model);
        printf("%d ", cars[i].year);
        printf("%d ", cars[i].city_mpg);
        printf("%d\n", cars[i].highway_mpg);
    }
}

int main() {
    FILE *input = fopen("cars.txt", "r");
    struct Car cars[9];
    int i;
    char make[20], model[20];
    int year, city_mpg, highway_mpg;
    if (input == NULL) printf("Unable to open file.\n");
    else {
        for (i = 0; i < 9; i++) {
            fscanf(input, "%s %s %d %d %d",
                make,
                model,
                &year,
                &city_mpg,
                &highway_mpg);

            cars[i].make = make;
            cars[i].model = model;
            cars[i].year = year;
            cars[i].city_mpg = city_mpg;
            cars[i].highway_mpg = highway_mpg;

            printf("%s ", cars[i].make);
            printf("%s ", cars[i].model);
            printf("%d ", cars[i].year);
            printf("%d ", cars[i].city_mpg);
            printf("%d\n", cars[i].highway_mpg);
        }
        printf("\n");
        print_cars(cars, 9);

        selection_sort(cars, 9);

        write_cars(cars, 9);

    }
    return 0;
}

这是我得到的结果:

Mercury Sable 2009 18 28
Jeep Wrangler 2016 17 21
Honda Civic 2015 31 41
Toyota Corolla 2015 30 42
Toyota Prius 2010 51 48
Ford Escape 2013 23 33
Ford Fusion 2013 25 37
Acura MDX 2014 20 28
Lexus RX 2013 32 28

Lexus RX 2009 18 28
Lexus RX 2016 17 21
Lexus RX 2015 31 41
Lexus RX 2015 30 42
Lexus RX 2010 51 48
Lexus RX 2013 23 33
Lexus RX 2013 25 37
Lexus RX 2014 20 28
Lexus RX 2013 32 28

这是我正在读取的文本文件:

Mercury Sable 2009 18 28
Jeep Wrangler 2016 17 21
Honda Civic 2015 31 41
Toyota Corolla 2015 30 42
Toyta Prius 2010 51 48
Ford Escape 2013 23 33
Ford Fusion 2013 25 37
Acura MDX 2014 20 28
Lexus RX 2013 32 28

您将每个 cars[i].make 设置为 make,将每个 cars[i].model 设置为 model。所以他们都指向同一个地方。如果汽车的品牌和型号不同,那应该如何工作?

您需要复制 makemodel 中的数据,并使 cars[i].makecars[i].model 指向该副本。否则,当您读入下一个品牌和型号时,您将覆盖您曾经存储过上一辆车的品牌和型号的唯一位置。

如果您的平台有strdup,您可以更改:

        cars[i].make = make;
        cars[i].model = model;

        cars[i].make = strdup(make);
        cars[i].model = strdup(model);

strdup函数分配一个新的内存块并将一个字符串复制到其中,返回一个指向新内存块的指针。