/* * PLANETS4 -- 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: planets4 [ ... ] * -- goes through argv using an array index * planet5 [ ... ] * -- goes through argv using pointers * * 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[]) { int i; /* counter in a for loop */ char **a; /* pointer in a for loops */ PLANET *tmp_planets; /* temporary to hold structure in swap */ PLANET **p, **q; /* pointers in for loops */ PLANET **min; /* points to planet with min diameter this pass */ /* * first, we load the planets */ /* be sure there *is* a set of planets to load! */ if (argc == 1){ fprintf(stderr, "Usage: %s planet_file [ ... ]\n", argv[0]); return(1); } /* now load them */ /* we use 2 different but equivalent ways, depending */ /* on the command name (planets4, use index; planets5 */ /* use pointers */ if (strcmp(argv[0], "planets4") == 0){ for(i = 1; i < argc; i++) if (!loadplanets(argv[i])){ fprintf(stderr, "Could not load planets from file %s\n", argv[i]); return(1); } } else{ for(a = argv + 1; *a != NULL; a++) if (!loadplanets(*a)){ fprintf(stderr, "Could not load planets from file %s\n", *a); 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[100]; /* 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 = malloc(sizeof(PLANET))) == NULL){ perror("malloc 1 failed!"); return(0); } /* now, allocate space for the name */ namelen = strlen(name); if ((tmp->name = 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); }