/***** BEGIN sales.c *****/ #include #include #include #include "sales.h" /** arrays **/ Sales salesTbl[ MaxSales ]; /* sales by account */ Sales* salesPtr[ MaxSales ]; /* pointers to salesTbl */ SalesPer salesPerTbl[ MaxSalesPer ]; /* sales personnel */ SalesPer* salesPerPtr[ MaxSalesPer ]; /* pointers to salesPerTbl */ /** array counts **/ int salesCnt, salesPerCnt; /** function declarations **/ void readSales( const char* infile ), readSalesPer( const char* infile ), quicksort( void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ) ), report( void ); void* findPivot( const void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ) ); int partition( void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ), void* pivot ), compAccId( const void* e1, const void* e2 ), compName( const void* e1, const void* e2 ); FILE* openOrExit( const char* file, const char* mode ); main() { /* read sales data and sort */ readSales( SalesFile ); quicksort( salesPtr, salesCnt, sizeof ( salesPtr[ 0 ] ), compAccId ); /* read salesperson data and sort */ readSalesPer( SalesPerFile ); quicksort( salesPerPtr, salesPerCnt, sizeof ( salesPerPtr[ 0 ] ), compName ); /* print sales report */ report(); return EXIT_SUCCESS; } /* Read data into array salesTbl and set SalesCnt */ void readSales( const char* infile ) { FILE* fptr; int i = 0; char buffer[ MaxBuffer + 2 ]; /* input buffer */ fptr = openOrExit( infile, "rb" ); salesCnt = 0; while ( fgets( buffer, MaxBuffer, fptr ) ) { sscanf( buffer, "%d %s %f %f", &salesTbl[ i ].accId, salesTbl[ i ].accName, &salesTbl[ i ].act, &salesTbl[ i ].proj ); i++; } fclose( fptr ); salesCnt = i; /* Set pointers in salesPtr to addresses of * corresponding elements in salesTbl. */ for ( i = 0; i < salesCnt; i++ ) salesPtr[ i ] = &salesTbl[ i ]; } /* Read data into array salesPerTbl and set SalesPerCnt */ void readSalesPer( const char* infile ) { FILE* fptr; int i = 0, j; char* del; char id[ MaxName + 1 ]; char buffer[ MaxBuffer + 2 ]; /* input buffer */ Sales temp, *tempPtr = &temp, **ret; fptr = openOrExit( infile, "rb" ); salesPerCnt = 0; while ( fgets( buffer, MaxBuffer, fptr ) ) { /* Read basic fields. */ sscanf( buffer, "%s %s %s %f %f", salesPerTbl[ i ].name, salesPerTbl[ i ].boss, salesPerTbl[ i ].reg, &salesPerTbl[ i ].base, &salesPerTbl[ i ].bonus ); /*** read account ids and set pointers to Sales structures ***/ salesPerTbl[ i ].accCnt = 0; j = 0; /* find accounts delimiter within buffer */ del = strrchr( buffer, AccDel ); del++; while ( *del && sscanf( del, "%s", id ) != EOF ) { tempPtr -> accId = atoi( id ); del += strlen( id ) + 1; /* move beyond current id */ /* Search for sales record by account id. */ if ( ret = bsearch( &tempPtr, salesPtr, salesCnt, sizeof ( salesPtr[ 0 ] ), compAccId ) ) { salesPerTbl[ i ].accCnt++; salesPerTbl[ i ].accs[ j++ ] = *ret; } } i++; } fclose( fptr ); salesPerCnt = i; /* Copy address of sales table entries * into pointer array. */ for ( i = 0; i < salesPerCnt; i++ ) salesPerPtr[ i ] = &salesPerTbl[ i ]; } /* Open file in specified mode, returning * file pointer if successfull; otherwise, * issue warning message and exit program. */ FILE* openOrExit( const char* file, const char* mode ) { FILE* fptr; if ( NULL == ( fptr = fopen( file, mode ) ) ) { fprintf( stderr, "!! Can't open %s in mode %s. Exiting. !!\n", file, mode ); exit( EXIT_SUCCESS ); } return fptr; } void quicksort( void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ) ) { void* pivot; int i; /* If array not yet sorted: * (1) find a pivot * (2) partition into two subarrays, left and right * (3) quicksort the left subarray * (4) quicksort the right subarray */ if ( pivot = findPivot( array, count, size, comp ) ) { i = partition( array, count, size, comp, pivot ); quicksort( array, i, size, comp ); quicksort( ( char* ) array + i * size, count - i, size, comp ); } } /* Return the larger of the first element and any * other that differs from it. If all elements the * same, return NULL. */ void* findPivot( const void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ) ) { int i = 1, flag; void* next; while ( i < count ) { next = ( char* ) array + i * size; flag = comp( array, next ); if ( flag > 0 ) /* array[ 0 ] > array[ i ] */ return array; else if ( flag < 0 ) /* array[ i ] > array[ 0 ] */ return next; else /* array[ 0 ] == array[ i ] */ i++; } return NULL; /* all elements the same */ } /* Partition an array into two subarrays, the first * holding elements <= pivot and the second holding * elements > pivot. */ int partition( void* array, size_t count, size_t size, int ( *comp )( const void* e1, const void* e2 ), void* pivot ) { int left = 0, right = count - 1, n = count; void* next; char temp[ MaxBuffer ]; if ( size >= MaxBuffer ) { fprintf( stderr, "\n!! MaxBuffer too small. Exiting. !!\n\n" ); exit( EXIT_SUCCESS ); } while ( left <= right ) { /* Search from left to right for 1st element >= pivot. */ next = ( char* ) array + left * size; while ( left < n && comp( next, pivot ) < 0 ) { left++; next = ( char* ) array + left * size; } /* Search from right to left for 1st element < pivot. */ next = ( char* ) array + right * size; while ( right >= 0 && comp( next, pivot ) >= 0 ) { right--; next = ( char* ) array + right * size; } /* Swap current left and right elements to put them in * relative order with respect to each other and pivot. */ if ( left < right ) { char *p1 = ( char* ) array + left * size, *p2 = ( char* ) array + right * size; memcpy( temp, p1, size ); memcpy( p1, p2, size ); memcpy( p2, temp, size ); left++; right--; } } return left; } int compAccId( const void* e1, const void* e2 ) { Sales *t1 = *( ( Sales** ) e1 ), *t2 = *( ( Sales** ) e2 ); return t1 -> accId - t2 -> accId; } int compName( const void* e1, const void* e2 ) { SalesPer *t1 = *( ( SalesPer** ) e1 ), *t2 = *( ( SalesPer** ) e2 ); return strcmp( t1 -> name, t2 -> name ); } void report( void ) { int i, j; printf( "\nSales report by salesperson:\n\n" ); for ( i = 0; i < salesPerCnt; i++ ) { printf( "\n\tSalesperson: %s\n", salesPerPtr[ i ] -> name ); printf( "\tSales coach: %s\n", salesPerPtr[ i ] -> boss ); printf( "\tSales region: %s\n", salesPerPtr[ i ] -> reg ); printf( "\tBase salary and bonus: %.2f %.2f\n", salesPerPtr[ i ] -> base, salesPerPtr[ i ] -> bonus ); printf( "\t%d Account(s): \n", salesPerPtr[ i ] -> accCnt ); for ( j = 0; j < salesPerPtr[ i ] -> accCnt; j++ ) { printf( "\n" ); printf( "\t\tName: %s\n", salesPerPtr[ i ] -> accs[ j ] -> accName ); printf( "\t\tId: %d\n", salesPerPtr[ i ] -> accs[ j ] -> accId ); printf( "\t\tProjected: %.2f\n", salesPerPtr[ i ] -> accs[ j ] -> proj ); printf( "\t\tActual: %.2f\n", salesPerPtr[ i ] -> accs[ j ] -> act ); } } } /***** END sales.c *****/