/* * PLANETS3 -- sort and print planets in increasing order of diameter * this uses structures to hold names and diameters; these are allocated * as the planets and their diameters are read in from a file * * Usage: planets3 * * Inputs: none * Outputs: prints the sorted list * Arguments: name of file containing planet data * the data has the form: * name diameter * where "name" has no blanks * * Written by Matt Bishop for ECS 30 * version 1 November 19, 2015 */ #include #include #include /* * useful macros */ #define MAXPLANETS 100 /* maximum number of planets */ #define MAXNAMELEN 100 /* maximum length of planet name */ /* * structure that holds planet name and diameter */ struct celestial { char *name; /* name of planet */ int diameter; /* diameter of planet */ }; /* define a type to make things easier */ typedef struct celestial PLANET; /* * array of pointers to planet names and diameters * we allocate the space for each PLANET as we * read one in */ PLANET *planets[MAXPLANETS]; /* array of pointers */ int nplanets = 0; /* number of planets */ /* * prototypes */ int loadplanets(char *); /* function to load planet data (below) */ /* * main routine */ int main(int argc, char *argv[]) { PLANET *tmp_planets; /* temporary to hold pointer in swap */ PLANET **p, **q; /* pointers in for loops */ PLANET **min; /* points entry of planet with min diameter so far */ /* * first, we load the planets */ /* be sure there *is* a set of planets to load! */ if (argc != 2){ fprintf(stderr, "Usage: %s planet_file\n", argv[0]); return(1); } /* now load them */ if (!loadplanets(argv[1])){ fprintf(stderr, "Could not load planets\n"); return(1); } /* * do selection sort * make repeated passes through the list, * putting the planet with the minimum diameter in the * first position, and then sorting the rest of the list */ for(p = planets; p < &planets[nplanets]; p++){ /* assume first one is minimum diameter */ min = p; /* * now find out if it *really* is the minimum * if not, swap it with the minimum and continue */ for(q = p + 1; q < &planets[nplanets]; q++) if ((*q)->diameter < (*min)->diameter) min = q; /* * if we found a new minimum -- swap */ if (min != p){ tmp_planets = *p; *p = *min; *min = tmp_planets; } } /* * now print out the planets and diameters * in increasing order of diameter */ printf("Planets in order of size of diameters:\n"); for(p = planets; p < &planets[nplanets]; p++) printf("%7dkm %s\n", (*p)->diameter, (*p)->name); /* * all done! */ return(0); } /* * function to load planet data from a file * * RETURNS: 0 on success, 1 if there's a problem * * NOTE: if the load fails, it does *not* free * space already allocated */ int loadplanets(char *fname) { FILE *fp; /* points to input file */ int lineno = 1; /* current input line number */ int n; /* number of inputs scanf read */ PLANET *tmp; /* points to space for new planet */ char name[MAXNAMELEN]; /* planet name */ int namelen; /* length of name read */ int diameter; /* diameter in km */ /* * open the file */ if ((fp = fopen(fname, "r")) == NULL){ perror(fname); return(1); } /* * read in the lines; if you get < 2, it better be EOF! */ while(nplanets < MAXPLANETS && (n = fscanf(fp, "%s %d\n", name, &diameter)) == 2){ /* get one -- allocate space for the structure */ if ((tmp = (PLANET *) malloc(sizeof(PLANET))) == NULL){ perror("malloc 1 failed!"); return(0); } /* now, allocate space for the name */ namelen = strlen(name); if ((tmp->name = (char *) malloc((namelen+1) * sizeof(char))) == NULL){ perror("malloc 2 failed!"); return(0); } /* put the data into the structure */ (void) strcpy(tmp->name, name); tmp->diameter = diameter; /* and now save the structure in the array */ planets[nplanets++] = tmp; /* go to the next line */ lineno++; } /* * see why you dropped out */ if (n != EOF){ fprintf(stderr, "Malformed line %d\n", lineno); return(0); } /* * now close the file */ (void) fclose(fp); return(1); }