/* Program to sort a file, "lst11-1.old", into a new file, "lst11-1.new". Files contain employee data records (max 100). Records have four lines: (1) Surname (20 chars), Given names (50 chars) (2) Address line 1 (60 chars) (3) Address line 2 (60 chars) (4) Position title (40 chars), Payroll no. (long), age (int), Sex (char, M or F), salary (double), Department no. (int). File to be sorted on: surnames, then given names, then payroll no. (Uses a structure to encapsulate all data belonging to one employee.) */ #include #include #include #define MAX_STAFF (50) #define ADDRESS_SIZE (61) #define SURNAME_SIZE (21) #define GIVEN_NAME_SIZE (51) #define TITLE_SIZE (41) /* The following are format strings used in function "load_data". If the above #define sizes are altered, these must also be changed. */ #define address_format "%60[^\n]%*c" /* meaning: read up to 60 chars, */ /* stopping at a newline, then */ /* read and discard the newline. */ #define name_format "%20[^\n]%50[^\n]%*c" #define title_format "%40[^\n]%ld%d %c%lf%d%*c" /**** staff_data: The main structure used to store employee data. ****/ typedef struct { char surname[SURNAME_SIZE]; char given_names[GIVEN_NAME_SIZE]; char address1[ADDRESS_SIZE]; char address2[ADDRESS_SIZE]; char title[TITLE_SIZE]; long payroll_no; int age; int department; double salary; char sex; } staff_data; /* Function Declarations: */ FILE *file_open(char name[], char access_mode[]); /* See listing 10-7 */ int load_data(staff_data staff[]); void sort_data(staff_data *staff[], int numb_staff); void write_data(staff_data *staff[], int numb_staff); /******* The functions themselves: *******/ main() { staff_data staff[MAX_STAFF]; staff_data *pstaff[MAX_STAFF]; /* array of pointers to staff_datas */ int numb_staff; /* How many employee records are read */ /* Set up pointers: */ for (numb_staff=0; numb_staff= 0) { /* EOF not detected on first fscanf */ if ( status < 2 || fscanf(inf, address_format, staff[number].address1) < 1 || fscanf(inf, address_format, staff[number].address2) < 1 || fscanf ( inf, title_format, staff[number].title, &staff[number].payroll_no, &staff[number].age, &staff[number].sex, &staff[number].salary, &staff[number].department ) < 6 ) { /* This branch is selected on error in any of the fscanf calls, and on EOF in any call except the first one. */ fprintf(stderr, "Error in input file, record %d\n", number); exit(EXIT_FAILURE); } } number++; } while (number=0); fclose(inf); return number - 1; /* The loop counted one too many. */ } int in_wrong_order(staff_data *pstaff[], int which); /* Compares items at indices which & which+1, tells if disordered. */ void sort_data(staff_data *pstaff[], int numb_staff) { staff_data *temp_ptr; int i, j; for (i=numb_staff-1; i>0; i--) { /* scan numb_staff-1 times */ for (j=1; j<=i; j++) { /* Scan the elements still unsorted. */ if (in_wrong_order(pstaff,j-1)) { temp_ptr = pstaff[j-1]; /* Swap elements */ pstaff[j-1] = pstaff[j]; pstaff[j] = temp_ptr; } } } } int in_wrong_order(staff_data *pstaff[], int which) { /* Compares items at indices which & which+1, tells if disordered. Do three tests, stop at the first where the items differ. */ int order; /* will be <0 for less, 0 for ==, >0 for greater */ order = strcmp(pstaff[which]->surname, pstaff[which+1]->surname); if (order==0) { /* surnames ==, must compare given names. */ order = strcmp( pstaff[which]->given_names, pstaff[which+1]->given_names ); if (order==0) { /* given names ==, must compare payroll. */ return (pstaff[which]->payroll_no>pstaff[which+1]->payroll_no); } } return (order>0); /* Since (order>0) means they are wrongly ordered. */ } void write_data(staff_data *pstaff[], int numb_staff) { FILE *outf; int i; outf = file_open("lst11-1.new", "w"); /* See listing 10-7 */ for (i=0; isurname, pstaff[i]->given_names, pstaff[i]->address1, pstaff[i]->address2, TITLE_SIZE-1, pstaff[i]->title, pstaff[i]->payroll_no, pstaff[i]->age, pstaff[i]->sex, pstaff[i]->salary, pstaff[i]->department ); } fclose(outf); } /* The following #ifdef includes the file_open function; if you have it in a personal function library, you may wish to delete these lines and link the two files separately. */ #ifdef __cplusplus #include "lst10-7.cpp" /* or maybe "lst10-7.cxx" */ #else #include "lst10-7.c" #endif