planets4.c

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



UC Davis sigil
Matt Bishop
Office: 2209 Watershed Sciences
Phone: +1 (530) 752-8060
Email: mabishop@ucdavis.edu
ECS 36A, Programming & Problem Solving
Version of April 2, 2024 at 12:13PM

You can get the raw source code here.

Valid HTML 4.01 Transitional Built with BBEdit Built on a Macintosh