/*
* 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 <filename> [ ... ]
* -- goes through argv using an array index
* planet5 <filename> [ ... ]
* -- 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* 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);
}
|
ECS 36A, Programming & Problem Solving Version of April 2, 2024 at 12:13PM
|
You can get the raw source code here. |