C结构数据在迭代循环外不一致

C结构数据在迭代循环外不一致,c,struct,printf,scanf,consistency,C,Struct,Printf,Scanf,Consistency,我有一个程序,我希望使用fscanf将车内数据读入for循环中的结构数组(我知道,我应该使用fgets或其他东西,但这是此辅助所必需的),并通过平均MPG对数据进行排序,并使用fprintf将排序后的数据输出到新文件。在我的main函数中的for循环中,当我读取数据时,作为一种调试功能,我打印分配给struct[I]的所有数据,然后继续到包含后续struct对象数据的文本文件中的下一行。然而,在输入了所有数据并且到目前为止一切看起来都很好之后,我重新打印了struct数组中的所有信息,前两个数据

我有一个程序,我希望使用fscanf将车内数据读入for循环中的结构数组(我知道,我应该使用fgets或其他东西,但这是此辅助所必需的),并通过平均MPG对数据进行排序,并使用fprintf将排序后的数据输出到新文件。在我的main函数中的for循环中,当我读取数据时,作为一种调试功能,我打印分配给struct[I]的所有数据,然后继续到包含后续struct对象数据的文本文件中的下一行。然而,在输入了所有数据并且到目前为止一切看起来都很好之后,我重新打印了struct数组中的所有信息,前两个数据区域“make”和“model”都采用了最后一个指定的struct的字符串。我已经修复了几个小时的错误,但没有找到解决方案。有人能告诉我我的代码有什么问题吗? 提前谢谢大家

// 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
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
。所以它们都指向同一个地方。如果汽车的品牌和型号不同,那该怎么办

您需要在
make
model
和make
cars[i]中复制数据。make
cars[i]。model
指向该副本。否则,当您阅读下一个品牌和型号时,您将覆盖存储前一辆车的品牌和型号的唯一位置

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

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


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

显示正确的值是因为它们在重写之前是正确的。你每次都在同一个地方读
make
model
,每次都会覆盖你上次读到的内容。我还是有点迷路,因为我正在打印来自结构变量“cars[I].make”和“cars[I].model”的信息,据我所知,我不会再调用任何对结构变量的写操作,只有主变量“make”和“model”,它们是fscanf在将值写入car[i]之前写入的“中间人”变量。make和car[i]。model也尝试了strdup,但visual studio不支持它。这给我带来了一个编译错误。@4ur0r4您缺少一个基本点--
cars[i]。model
是一个指针。它指向
模型
。因此,如果您更改
模型
,那么您正在更改字符串
cars[i]。模型
指向。您需要将读入的数据复制一份,然后制作
cars[i]。model
指向副本。您是否同意以下两种说法:1)每次读入模型时,您都读入到相同的位置。2) 你在哪里都不会复制你读到的任何字符串,我会的!我以前不知道对结构元素的引用是指针,而不是实际的元素本身。多亏了你,我才明白!
        cars[i].make = make;
        cars[i].model = model;
        cars[i].make = strdup(make);
        cars[i].model = strdup(model);