/* 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]; /* Data for all employees */ int numb_staff; /* How many employee records are read */ numb_staff = load_data(staff); sort_data(staff, numb_staff); write_data(staff, numb_staff); return 0; } /* load_data: Fills the array with data from lst11-1.old, until MAX_SIZE items read or EOF. Returns a count of the number of employee records input. If an input error (except for EOF) occurs, a message is printed and the program terminates. */ int load_data(staff_data staff[]) { int number=0; /* How many employee records are read */ int status; /* result of fscanf call */ FILE *inf; inf = file_open("lst11-1.old", "r"); /* See listing 10-7 */ do { /* Load one record at a time until failure */ status = fscanf ( inf, name_format, staff[number].surname, staff[number].given_names ); if (status >= 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 staff[], int which); /* Compares items at indices which & which+1, tells if disordered. */ void sort_data(staff_data staff[], int numb_staff) { staff_data temp_employee; 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(staff,j-1)) { temp_employee = staff[j-1]; /* Swap elements */ staff[j-1] = staff[j]; staff[j] = temp_employee; } } } } int in_wrong_order(staff_data staff[], 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(staff[which].surname, staff[which+1].surname); if (order==0) { /* surnames ==, must compare given names. */ order = strcmp( staff[which].given_names, staff[which+1].given_names ); if (order==0) { /* given names ==, must compare payroll. */ return (staff[which].payroll_no>staff[which+1].payroll_no); } } return (order>0); /* Since (order>0) means they are wrongly ordered. */ } void write_data(staff_data staff[], int numb_staff) { FILE *outf; int i; outf = file_open("lst11-1.new", "w"); /* See listing 10-7 */ for (i=0; i