/* busrep6.c - functions for use with awkfilt4.c to: 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); /*--- global data */ /* arrays totals[][] are used to accumulate then print various totals */ #define LEVELS 2 #define ACCUMS 5 static float totals[LEVELS][ACCUMS]; /* elements of the array totals are accessed using the */ /* following defines for the possible index values of ACCUMS */ #define QOH_START 0 #define RECEIPTS 1 #define WITHDRAWALS 2 #define QOH_END 3 #define VALUE 4 /* 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; /*--- function prototypes - all in #include files */ /*==================================================================*/ /*==================== awk-like BEGIN processing ===================*/ /*==================================================================*/ int begin(char* dest, char* source) /* user supplied function */ { int j = 0; /* loop control - LEVELS*/ int k = 0; /* loop control - ACCUMS*/ /* clear the screen */ clrscr(); /* initialize totals to zeros */ for (j = 0; j < LEVELS; j++) { for (k = 0; k < ACCUMS; k++) { totals[j][k] = 0.0; } } /* to clear warnings */ *dest=NULL; *source=NULL; return 1; /* by default write nothing to stdout at start */ } /*==================================================================*/ /*================== awk-like END processing =======================*/ /*==================================================================*/ int finish(char* dest, char* source) /* user supplied function */ { char temp[1256]; /*--- format final total line */ sprintf(temp, "Totals: Quantity on Hand at Start of Period %9.2f\n" " Number of Receipts %9.2f\n" " Number of Withdrawals %9.2f\n" " Quantity on Hand as End of Period %9.2f\n" " VALUE = $%1.2f\n", totals[1][QOH_START], totals[1][RECEIPTS], totals[1][WITHDRAWALS], totals[1][QOH_END], totals[1][VALUE]); /*--- arrange to display/print */ strcat(dest, "\n===============================================================================\n"); strcat(dest, temp); *source=NULL; return 0; } /*==================================================================*/ /*====================== per-record processing =======================*/ /*==================================================================*/ int process(char* dest, char* source) /* user supplied function */ { int word_count = 0; char* words[8]; /* words from input (8 is big enough ... expecting 7) */ char temp[281]; /* used in formatting */ float QOH_end = 0; /* Quantity on hand at end of period, whole number 5 digits */ /* split up input line into array*/ word_count = split_tokens(source, " \t", 7, words); /* word_count should be 7 ... check and flag error if necessary */ if (word_count != 7) { strcpy(dest, source); /*--- by default copy source -> dest */ return 99; } /*--- accumulate totals into DETAIL-level [0] of array */ QOH_end = atof(words[4]) + atof(words[5]) - atof(words[6]); totals[0][QOH_START] = totals[0][QOH_START] + atof(words[4]); totals[0][RECEIPTS] = totals[0][RECEIPTS] + atof(words[5]); totals[0][WITHDRAWALS] = totals[0][WITHDRAWALS] + atof(words[6]); totals[0][QOH_END] = totals[0][QOH_END] + QOH_end; totals[0][VALUE] = totals[0][VALUE] + (atof(words[3]) * QOH_end); /*--- format detail line for output */ sprintf(temp, "%-3s %-5s %-12s %5.2f %5d %5d %5d %5.1f %7.2f", words[0], words[1], words[2], atof(words[3]), atoi(words[4]), atoi(words[5]), atoi(words[6]), QOH_end, atof(words[3]) * atof(words[4]) ); strcpy(dest, temp); /*--- by default copy source -> dest */ return 0; /*--- by default cause dest to go to stdout */ } /*==================================================================*/ /* ================ format header lines =================== */ /*==================================================================*/ int do_header(char* heading) { char temp[281]; /* used in formatting */ /*--- format heading line */ sprintf(heading, "\f\n\n%-5s %-5s %-12s %-7s %-6s %-7s %-10s %-6s %-5s\n", "Inv", "Inv", "Inv", "Item", "QOH", "Receipt", "Withdrawal", "QOH", "Value"); sprintf(temp, "%-5s %-5s %-12s %-7s %-6s %-6s \n", "Class", "Code", "Des", "Cost", "Start", "End"); /* add next line on heading */ strcat(heading, temp); /*--- arrange to display/print */ strcat(heading, "==============================================================================="); 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 */ /* change */ word_count = split_tokens(record, " \t", 7, 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", previous, totals[0][QOH_END], totals[0][VALUE]); strcat(dest, "\n===============================================================================\n"); strcat(dest, temp); } /*==================================================================*/ /* =========== format level break headings ============ */ /*==================================================================*/ void do_level_header(char* dest) { /*--- format heading line */ sprintf(dest, "-------Customer %s---------%s\n", current, continued); }