2017-04-23 5 views
-2

J'ai un programme où je suis supposé lire dans les données de voiture dans un tableau struct dans une boucle for en utilisant fscanf (je sais, je devrais utiliser fgets ou autre chose, mais il est requis pour cette assertion) et trier les données par MPG moyen et sortir les données triées dans un nouveau fichier en utilisant fprintf. Dans ma boucle for de ma fonction principale lorsque je lis les données, en tant que fonctionnalité de débogage, j'imprime toutes les données affectées à la structure [i] avant de passer à la ligne suivante dans le fichier texte contenant les données pour la suite objet struct. Cependant, après que toutes les données aient été saisies et que tout semble correct jusqu'à présent, je réimprime toutes les informations dans le tableau struct, et les deux premières régions de données "make" et "model" prennent toutes la chaîne de la dernière structure attribué. J'ai été bugfixing pendant des heures et n'ai trouvé aucune solution. Quelqu'un peut-il me dire ce que je fais mal avec mon code? Merci d'avance!C données struct ne pas être cohérent en dehors de la boucle itérative

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

Ceci est le résultat que je reçois:

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 

Ceci est le fichier texte je lis:

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 

Répondre

0

Vous définissez tous les cars[i].make-make et tous les cars[i].model à model . Donc, ils pointent tous vers le même endroit. Comment cela est-il supposé fonctionner si les voitures sont de marques et de modèles différents?

Vous devez faire une copie des données dans make et model et de faire le point cars[i].make et cars[i].model à cette copie. Sinon, lorsque vous lirez la marque et le modèle suivants, vous écraserez le seul endroit où vous avez stocké la marque et le modèle de la voiture précédente.

Si votre plate-forme a strdup, vous pouvez changer:

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

à

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

La fonction strdup alloue une nouvelle partie de la mémoire et copie une chaîne en elle, renvoyant un pointeur sur la nouveau morceau de mémoire.

+0

Les valeurs correctes sont affichées parce qu'ils étaient corrects avant de les réenregistrés. Vous lisez 'make' et' model' au même endroit à chaque fois, écrasant chaque fois ce que vous avez lu auparavant. –

+0

Je suis encore un peu perdu parce que j'imprime des informations à partir des variables struct "cars [i] .make" et "cars [i] .model" et autant que je sache, je n'appelle plus d'écriture opérations sur les variables struct, seules les variables principales "make" et "model", qui sont des variables "middle-men" qui sont écrites par fscanf avant que leurs valeurs ne soient écrites dans car [i] .make et car [i ] .model Aussi, j'ai essayé strdup, mais Visual Studio ne le supporte pas. Cela me jette une erreur de compilation. – 4ur0r4

+0

@ 4ur0r4 Il vous manque un point fondamental - 'cars [i] .model' est un pointeur. Il indique 'model'. Donc si vous changez 'model', vous changez la chaîne' cars [i] .model'. Vous devez faire une copie des données que vous avez lues et faire pointer 'cars [i] .model' sur la copie. –

-1

Essayez de vider le tampon après avoir affecté les données à struct Car. Les données peuvent toujours être bloquées dans le flux d'entrée, puis affectées au mauvais emplacement.

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

espoir qui aide