#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 MoreInput (1) int compareP( const void* p1, const void* p2 ), compareS( const void* p1, const void* p2 ), input( char terms[ ][ MaxLen + 2 ] ); void search( char* termPtrs[ ], int n ); main() { char terms[ MaxRecs ][ MaxLen + 2 ], /* +2 for newline and null */ *termPtrs[ MaxRecs ]; int i, n; /* Read records from file. */ n = input( terms ); /* Copy addresses into pointer array. */ for ( i = 0; i < n; i++ ) termPtrs[ i ] = terms[ i ]; /* Sort the pointer array. */ qsort( termPtrs, /* array to be sorted */ n, /* element count */ sizeof ( termPtrs[ 0 ] ), /* element size */ compareP ); /* comparision function */ /* Allow user to search for terms. */ search( termPtrs, n ); return EXIT_SUCCESS; } /* Compare two strings. Return negative integer if the first * string precedes the second, positive integer if the second * string precedes the first, and 0 if the strings are the same. */ int compareP( const void* p1, const void* p2 ) { char** s1 = ( char** ) p1; /* cast void* to char** */ char** s2 = ( char** ) p2; /* cast void* to char** */ return strncmp( *s1, *s2, TermLen ); } /* Compare two strings. Same semantics as compareP. */ int compareS( const void* p1, const void* p2 ) { char* s1 = ( char* ) p1; char* s2 = ( char* ) p2; return strncmp( s1, s2, TermLen ); } /* Prompt user for term to be searched for until user tires. */ void search( char* termPtrs[ ], /* pointers to terms */ int n ) /* how many terms */ { char ans[ 10 ]; /* search again? */ char key[ MaxLen + 2 ]; /* term searched for */ char* keyPtr = key; /* passed to bsearch */ char** ptr; /* returned from bsearch */ 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 ( ( ptr = bsearch( &keyPtr, /* searched for */ termPtrs, /* pointers to terms */ n, /* array count */ sizeof ( termPtrs[ 0 ] ), /* element size */ compareP ) ) == NULL ) { /* not found */ key[ len ] = '\0'; /* knock off padded blanks */ printf( "%s not found.\n", key ); } else printf( "%s\n", *ptr ); /* term + definition */ printf( "Again? (y/n) " ); scanf( "%s", ans ); } while ( 'Y' == ans[ 0 ] || 'y' == ans[ 0 ] ); } int input( char terms[ ][ MaxLen + 2 ] ) { char temp[ MaxLen + 2 ]; char *ptr; FILE* infile; int i = 0; /* 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( temp, MaxLen + 2, infile ); if ( feof( infile ) || i + 1 >= MaxRecs ) break; else { /* Drop newline. */ if ( ( ptr = strrchr( temp, '\n' ) ) != NULL ) *ptr = '\0'; /* Add if not already in array. */ lsearch( temp, /* next string */ terms, /* array of strings */ &i, /* counter address */ sizeof ( terms[ 0 ] ), /* element size */ compareS ); /* comparison function */ } } fclose( infile ); return i; /* number of records read */ }