#include #include #include /* The program reads up to MaxRecs from the file * terms.dat into the two-dimensional array terms. * The records occur one to a line, with a maximum * length of MaxLen. Each record has two fields and * is formatted as follows: * Length: 15 50 * * Columns: 1 15 17 66 * If a term is less than 15 characters, then the * remaining characters are blanks. The term's definition * always begins in column 17, and no term is longer than * 15 characters. * * After reading the records, the program sorts them * and then allows the user to search for terms. If * a term is found, its definition is printed; otherwise, * a failure message is printed. */ #define Infile "terms.dat" #define MaxRecs (10) #define MaxLen (66) /* 15 for key + 1 blank + 50 for definition */ #define TermLen (15) #define NoFind (-999) /* returned on search failure */ #define MoreInput (1) void swap( char terms[ ][ MaxLen + 2 ], int i, int j ), sort( char terms[ ][ MaxLen + 2 ], int n ), search( char terms[ ][ MaxLen + 2 ], int n ); int bin_search( char key[ ], char terms[ ][ MaxLen + 2 ], int n ), input( char terms[ ][ MaxLen + 2 ] ); main() { char terms[ MaxRecs ][ MaxLen + 2 ]; /* +2 for newline and null */ int n; /* Read records from file. */ n = input( terms ); /* Sort the array. */ sort( terms, n ); /* Allow user to search for terms. */ search( terms, n ); return EXIT_SUCCESS; } /* Swap two strings in an array. */ void swap( char terms[ ][ MaxLen + 2 ], int i, int j ) { char temp[ MaxLen + 2 ]; strcpy( temp, terms[ i ] ); strcpy( terms[ i ], terms[ j ] ); strcpy( terms[ j ], temp ); } /* Selection sort an array of char. The algorithm can be sketched * as follows: * 1. Repeat steps 2 and 3 for i = 0,1,...,n-1. * 2. Select smallest among terms[ i ],terms[ i+1 ],...,terms[ n-1 ]. * 3. Swap smallest with terms[ i ]. */ void sort( char terms[ ][ MaxLen + 2 ], int n ) { int smallest, i, j; /* Loop n-1 times, selecting smallest each time. */ for ( i = 0; i < n - 1; i++ ) { smallest = i; /* assume smallest at index i */ /* Compare smallest against remaining strings. */ for ( j = i + 1; j < n; j++ ) if ( strcmp( terms[ j ], terms[ smallest ] ) < 0 ) smallest = j; /* Swap smallest and term[ i ]. */ if ( i != smallest ) swap( terms, i, smallest ); } } /* Search array of terms and definitions for a user-specified * term. If found, return its index in array; else return NoFind. * The search is binary search, which can be sketched as follows: * 1. Repeat steps 2 thru 4 until either key is found (success) * or there is nothing left to search (failure). * 2. Find (approximate) midpoint in array. * 3. Compare midpoint term with key. If they match, return index. * 4. If key is less than midpoint term, search first half of * array; otherwise, search second half of array. */ int bin_search( char key[ ], char terms[ ][ MaxLen + 2 ], int n ) { int first = 0, /* first term in array */ last = n - 1, /* last positiion in array */ mid, /* approximate midpoint */ flag; /* result of key versus term comparison */ while ( first <= last ) { mid = ( first + last ) / 2; flag = strncmp( key, terms[ mid ], TermLen ); if ( 0 == flag ) /* success */ return mid; else if ( flag > 0 ) /* search right half */ first = mid + 1; else last = mid - 1; /* search left half */ } return NoFind; /* failure */ } /* Prompt user for term to be searched for until user tires. */ void search( char terms[ ][ MaxLen + 2 ], /* searched */ int n ) /* how many terms */ { char ans[ 10 ]; /* search again? */ char key[ MaxLen + 2 ]; /* term searched for */ int i, len; /* Search until user tires. */ do { printf( "\nTerm? " ); scanf( "%s", key ); /* Pad key with blanks as needed. */ len = strlen( key ); for ( i = len; i < TermLen; i++ ) key[ i ] = ' '; key[ i ] = '\0'; /* null terminate */ if ( ( i = bin_search( key, terms, n ) ) == NoFind ) { key[ len ] = '\0'; /* knock off padded blanks */ printf( "%s not found.\n", key ); } else printf( "%s\n", terms[ i ] ); /* term + definition */ printf( "Again? (y/n) " ); scanf( "%s", ans ); } while ( 'Y' == ans[ 0 ] || 'y' == ans[ 0 ] ); } /* Read records from file into two-dimensional array, * returning how many were read. */ int input( char terms[ ][ MaxLen + 2 ] ) { FILE* infile; int i = 0, len; /* Open input file and read records into array. */ if ( ( infile = fopen( Infile, "r" ) ) == NULL ) { fprintf( stderr, "Can't open %s so exiting.\n", Infile ); exit( EXIT_SUCCESS ); } while ( MoreInput ) { fgets( terms[ i ], MaxLen + 2, infile ); if ( feof( infile ) || i + 1 >= MaxRecs ) break; else { len = strlen( terms[ i ] ); terms[ i ][ len - 1 ] = '\0'; /* drop newline */ i++; } } fclose( infile ); return i; /* number of records read */ }