/* ---------------------------------------------------------------------------- ** Figures 22.2: Using command-line arguments. ** 22.3: Decoding command-line arguments, setup(). ** 22.4: A revised sort function. ** 20.15: Input into an array. ** 20.16: Output from an array. ** ---------------------------------------------------------------------------- */ #include "tools.h" typedef enum { ascend, descend } order_t; string labels[] = { "ascending", "descending" }; typedef struct { float* data; int n; int max; order_t order; } data_pack; void setup( int argc, string argv[], stream* inp, stream* outp, data_pack* sortp ); void get_data( data_pack* sort, stream instream ); void print_data( data_pack sort, stream outstream ); void sort_data( data_pack sort ); /* ------------------------------------------------------------------------- */ void main( int argc, string argv[] ) { stream in_str, out_str; /* Streams for input and output. */ data_pack sort; /* Pointer to array of numbers. */ say( "\n Sort program." ); setup( argc, argv, &in_str, &out_str, &sort ); get_data( &sort, in_str ); say( " %i data items read; sorting in %s order.", sort.n, labels[sort.order] ); sort_data( sort ); say( " Data sorted; writing to file %s.", argv[argc-1] ); print_data( sort, out_str ); bye(); } /* ---------------------------------------------------------------------------- ** Decode and process the command-line arguments. */ void setup( int argc, string argv[], stream* inp, stream* outp, data_pack* sortp ) { char* last; /* To test for proper number conversion. */ long int n; /* Number of data items. */ int start = argc-3; /* First required argument. */ if (argc < 4 || argc > 5) fatal( "\n Usage: %s [-ad] num infile outfile \n", argv[0] ); /* -------------------------------------------------------- Open streams */ *inp = fopen( argv[start + 1], "r" ); if (*inp == NULL) fatal( "\n Cannot open %s for reading.", argv[start + 1] ); *outp = fopen( argv[start + 2], "w" ); if (*outp == NULL) fatal( "\n Cannot open %s for writing.", argv[start + 2] ); /* ----- Convert size from string to numeric format and allocate memory. */ n = strtol( argv[start], &last, 10 ); if (*last != '\0') fatal( "\n Error: %s is not an integer.", argv[start] ); if (n < 2) fatal( "\n Error: %i is too few items to sort.", n ); sortp->max = n; sortp->data = malloc( n * sizeof(float) ); if (sortp->data == NULL) fatal( "\n Too little memory for %i floats.", n ); /* ------------------ Pick up and check sort order (optional parameter). */ if (argc == 5) { if (strequal( argv[1], "-d" ) ) sortp->order = descend; else if (strequal( argv[1], "-a")) sortp->order = ascend; else fatal( "\n Sort order %s undefined.", argv[1] ); } else sortp->order = ascend; /* Default if switch is omitted. */ } /* ---------------------------------------------------------------------------- ** Read max data values from instream and store in ary. */ void get_data( data_pack* sortp, stream instream ) { int stream_status; float* cursor = sortp->data; float const* end = cursor + sortp->max; /* off-board sentinel */ for( ; cursorn = cursor-sortp->data; /* Actual # of items read. */ } /* ---------------------------------------------------------------------------- ** Print array values, one per line, to selected stream. --------------- */ void print_data( data_pack sort, stream outstream ) { float* cursor = sort.data; const float* end = cursor + sort.n; /* an off-board sentinel */ for( ; cursor < end; ++cursor) { fprintf( outstream, " %.7g\n", *cursor ); } } /* ---------------------------------------------------------------------------- ** Sort n values starting at head by insertion sort algorithm */ void sort_data( data_pack sort ) { float* end = sort.data + sort.n; /* Off-board sentinel. */ float* pass; /* First unsorted item; begin pass here. */ float* hole; /* Array slot containing no data. */ float newcomer; /* Data value being inserted. */ for ( pass = sort.data + 1; pass < end; ++pass ) { /* Pick up next item and insert into sorted portion of array. */ newcomer = *pass; for ( hole = pass; hole > sort.data; --hole ) { if (sort.order == ascend && (*(hole - 1) <= newcomer)) break; /* Insertion slot found... */ else if (sort.order == descend && (*(hole - 1) >= newcomer)) break; /* .... so leave loop. */ else *hole = *(hole - 1); /* else move item back one slot. */ } *hole = newcomer; /* Insert into sorted position. */ } }