/* busrep4.c - functions for use with awkfilt4.c to: - Assignment #4 for ISYS290-04 - with i/o files File Name : busrep4.c Course Number : ISYS 290 04 Student Name : Jason Gradziel Student Number : 826-135-535 Professors Name : Brian Perry Class Name : Wednesday 9:55 - 12:35 Lab Title : Assignment #4 BusReport with sub totals PRODUCE A TYPICAL BUSINESS REPORT this is a typical "list and total" report Input is text records containing five fields as follows, a simplified "cash register" example: customer id invoice number inventory item (code or description - developer's choice) quantity sold unit price of inventory item a static global two dimensional array (of float) is used to hold the totals FUNCTION begin intializes the array used to total the items formats the header line for the report FUNCTION process totals the items formats each detail line for the report FUNCTION finish formats the total line for the report ***NOTE*** all the actual output is done by the main() function */ #include #include #include #include "busrep4.h" /* function prototypes */ void clrscr(void); int split_tokens(char* str, char* delims, int expect, char* tokens[]); /* global data */ /* arrays totals[][] are used to accumulate then print various totals */ #define LEVELS 2 #define ACCUMS 3 static float totals[LEVELS][ACCUMS]; #define RECSIZE 21 /* elements of the array totals are accessed using the */ /* following defines for the possible index values of ACCUMS */ #define QTY 0 #define VALUE 1 #define COUNT 2 /* variables used to detect and process level change */ static char current[81] = "\0"; static char previous[81] = "\0"; static char continued[81] = "\0"; /* continued message */ /* vaiables used to control page-breaks */ static int page_number = 0; static int lines_per_page = 55; static int lines_printed = 55; static FILE *input; static int read_count = 0; /*--- function prototypes - all in #include files */ /*==================================================================*/ /*==================== awk-like BEGIN processing ===================*/ /*==================================================================*/ int begin(char* d, char* s) /* user supplied function */ { int j = 0; /* loop control - LEVELS*/ int k = 0; /* loop control - ACCUMS*/ /* clear screen */ clrscr(); /* initialize totals to zeros */ for (j = 0; j < LEVELS; j++) { for (k = 0; k < ACCUMS; k++) { totals[j][k] = 0.0; } } input = fopen("diskex1.dat","r"); if (input == NULL) { strcpy(d, "File open ERROR "); return 1; } else { strcpy(d,"File opened SUCCESSFULLY "); *s=NULL; return 1; } /*return 1; /* by default write nothing to stdout at start */ } /*==================================================================*/ /*================== awk-like END processing =======================*/ /*==================================================================*/ int finish(char* d, char* s) /* user supplied function */ { char temp[256]; /*--- format final total line */ sprintf(temp, "Total QTY and VALUE %9.2f %9.2f\nITEMS=%1.0f\n\n", totals[1][QTY], totals[1][VALUE], totals[1][COUNT]); /*--- arrange to display/print */ strcpy(d, "\n======================================================\n"); strcat(d, temp); fclose(input); sprintf(d,"File closed successfully %d records written", read_count); *s=NULL; return 0; } /*==================================================================*/ /*====================== per-record processing =======================*/ /*==================================================================*/ int process(char* d, char* s) /* user supplied function */ { int word_count = 0; char* words[6]; /* words from input (6 is big enough ... expecting 5) */ char temp[81]; /* used in formatting */ /* int rcount = 1; int acount = 0; int recno = 0; long offset = 0L; char temps[RECSIZE] = ""; */ /* split up input line into array*/ word_count = split_tokens(s, " \t", 5, words); /* word_count should be 5 ... check and flag error if necessary */ if (word_count != 5) { strcpy(d, s); /*--- by default copy source -> dest */ return 99; } /*--- accumulate totals into DETAIL-level [0] ofarray */ totals[0][QTY] = totals[0][QTY] + atof(words[3]); totals[0][VALUE] = totals[0][VALUE] + (atof(words[3]) * atof(words[4]) ); totals[0][COUNT]++; /*--- format detail line for output */ sprintf(temp, "%-5s %-5s %-20s %5.2f %7.2f %7.2f", words[0], words[1], words[2], atof(words[3]), atof(words[4]), atof(words[3]) * atof(words[4]) ); strcpy(d, temp); /*--- by default copy source -> dest */ /* recno = atoi(s); if (recno < 1) { sprintf(d, "Invalid record number: %s", s); return 0; } offset = (recno -1) * sizeof(temp); acount = fseek (input, offset, SEEK_SET); if (acount != 0) { sprintf(d, "Seek failed ... return value was %d", acount); return 0; } acount = fread(temps, sizeof(temps), rcount, input); if (acount != rcount) { sprintf(d, "Error reading record: %d", recno); return 0; } else { sprintf(d, "Record read successfully: %s", temps); read_count++; return 0; }*/ return 0; /*--- by default cause dest to go to stdout */ } /*==================================================================*/ /* ================ format header lines =================== */ /*==================================================================*/ int do_header(char* heading) { /*--- format heading line */ sprintf(heading, "\f\n\n%-5s %-5s %-20s %5s %7s %7s %s %d\n", "Cust#", "Inv#", "Inventory Item", "Qty", "Price", "Value","Page -", page_number); /*--- arrange to display/print */ strcat(heading, "======================================================\n"); return 0; } /* do_print.c - print with page control */ /*==================================================================*/ /* ============= does printing - handles page-breaks ======= */ /*==================================================================*/ void do_print (char* text) { int err = 0; /* holds return value of called funcs */ char output[256] = "\0"; /* holds output text */ /* ---- check if headings are needed ... do them if needed */ if (lines_printed >= lines_per_page) { page_number++; err = do_header(output); /* filled by function called */ if (!err) puts(output); /* output header */ lines_printed = 1 + count_lines(output); /* and do level break headings */ do_level_header(output); puts(output); lines_printed = 1 + count_lines(output); } /* ---- in any case (with or without headings */ puts(text); lines_printed = lines_printed + 1 + count_lines(text); } /*==================================================================*/ /* ================ counts lines in text =================== */ /*==================================================================*/ int count_lines(char* text) { int k = 0; /* loop control */ int count = 0; /* holds count of '\n' characters */ for (k = 0; text[k] != '\0'; k++) { if (text[k] == '\n') { count++; } } return count; } /*==================================================================*/ /* =========== detects and processes level breaks ============ */ /*==================================================================*/ int level_break(char* record) { /* variables which hold current and previous level-change data */ char temp[256]; int k = 0; /* loop control */ int word_count = 0; /* holds count of words found by split_tokens() */ char* words[6]; /* words from input (6 is big enough ... expecting 5) */ /* ------------OVERVIEW-------------------------------------- */ /* extract the data from the record that governs the level */ /* level change */ /* check "current" against "previous" to see if level change */ /* happened */ /* do the following in this sequemce */ /* - print totals for level change */ /* - roll up the totals and zero the detail level */ /* - do the headings for the level change */ /* - extract the data from the record that governs the level */ /* level change */ word_count = split_tokens(record, " \t", 5, words); /* words[0] now contains data which controls level-change */ strcpy(current, words[0]); /*--- check "current" against "previous" to see if level change */ /* happened */ if ( ! strcmp(current, previous)) { /* no level change */ strcpy(continued, "continued"); /* set continued message text */ return 0; } /*--- level change has been detected therefore */ /*--- do the following in this sequemce */ /*--- print totals for level change */ /* do not do totals at start of job */ if (previous[0] != '\0') { do_level_totals(temp); do_print(temp); /* - roll up the totals and zero the detail level */ for (k = 0; k < ACCUMS; k++) { totals[1][k] = totals[1][k] + totals[0][k]; /* roll totals */ totals[0][k] = 0.0; /* zero totals */ } /* set continued message text */ strcpy(continued, ""); } /*--- do the headings for the level change */ /* do not do headings after EOF or until after first record read */ if ( (previous[0] != '\0') && (current[0] != '~')) { do_level_header(temp); do_print(temp); } /*--- store new value of previous */ strcpy(previous, current); word_count++; return 1; } /*==================================================================*/ /* =========== formats level break totals ============ */ /*==================================================================*/ void do_level_totals(char* dest) { char temp[256] = "\0"; /*--- format total line */ sprintf(temp, "Total for %s %9.2f %9.2f\n\n", previous, totals[0][QTY], totals[0][VALUE]); strcpy(dest, "\n======================================================\n"); strcat(dest, temp); } /*==================================================================*/ /* =========== format level break headings ============ */ /*==================================================================*/ void do_level_header(char* d) { int rcount = 1; int acount = 0; int recno = 0; long offset = 0L; char temps[RECSIZE] = ""; recno = atoi(s); if (recno < 1) { sprintf(d, "Invalid record number: %s", s); return 0; } offset = (recno -1) * sizeof(temp); acount = fseek (input, offset, SEEK_SET); if (acount != 0) { sprintf(d, "Seek failed ... return value was %d", acount); return 0; } acount = fread(temps, sizeof(temps), rcount, input); if (acount != rcount) { sprintf(d, "Error reading record: %d", recno); return 0; } else { sprintf(d, "Record read successfully: %s", temps); read_count++; return 0; } /*--- format heading line */ sprintf(d, "\n-------Customer %s---------%s\n", current, continued); }