2017-04-23 57 views
-2

我有一个程序,我希望能够使用fscanf将汽车数据读入for循环中的struct数组(我知道,我应该使用fgets或其他东西,但是这是必要的),并通过平均MPG对数据进行排序,并使用fprintf将排序数据输出到新文件。在我的主循环中,当我读取数据时,作为调试功能,我打印所有分配给struct [i]的数据,然后继续到包含随后数据的文本文件中的下一行结构对象。然而,在所有的数据输入完毕并且一切看起来都很好之后,我重新打印了struct数组中的所有信息,并且前两个数据区域“make”和“model”都采用了最后一个结构体的字符串分配。我一直在修复这个小时,并没有找到解决办法。任何人都可以告诉我我的代码有什么问题吗? 谢谢大家!C结构数据在迭代循环外部失败一致

// 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 

回答

0

您可以设置每一个cars[i].makemakecars[i].modelmodel 。所以他们都指向同一个地方。如果汽车是不同的品牌和型号,那该如何运作呢?

您需要复制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函数分配的内存,并复制一个字符串转换成一个新的块,返回一个指针新的内存块。

+0

,显示出了正确的值,因为它们是正确的,你改写它们之前。你每次阅读'make'和'model'到同一个地方,每次覆盖你以前阅读的内容。 –

+0

我仍然有点失落,因为我打印来自结构变量“cars [i] .make”和“cars [i] .model”的信息,据我所知,我不再打电话给写信对结构变量的操作,只有主要变量“make”和“model”,它们是在fscanf被写入car [i]之前写入的“中间人”变量[i] .make和car [i ] .model 另外,我尝试了strdup,但visual studio不支持它。它扔给我一个编译错误。 – 4ur0r4

+0

@ 4ur0r4你错过了一个基本点 - '汽车[i] .model'是一个指针。它指向“模型”。所以如果你改变'model',你正在改变字符串'cars [i] .model'指向。您需要复制您读入的数据并使'cars [i] .model'指向副本。 –

-1

尝试在将数据分配给struct Car后清空缓冲区。数据可能仍然卡在输入流中,然后分配到错误的位置。

while(getchar() != '\n'); 

希望帮助