This is a(nother) long mail message. It includes several files, marked with FILE================== It includes the updated list and total report program with the modifcations to handle page breaks. It has been tested using Borland C++ v5.01. You may need to change the directory/location of the .h file included in busrep3.c The changes will be discussed in the classes this week. FILE============================= /* busrep3.c - functions for use with awkfilt3.c to: 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 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 "\bpbc50\busrep3\busrep3.h" /* function prototypes */ /*--- global data */ /* array totals[] is used to accumulate then print variouse totals */ /* elements of the array totals are accessed using the following defines */ static float totals[3]; #define QTY 0 #define VALUE 1 #define COUNT 2 static int page_number = 0; static int lines_per_page = 55; static int lines_printed = 55; /*--- function prototypes */ int begin(char* dest, char* source); /* user supplied function */ int process(char* dest, char* source); /* user supplied function */ int finish(char* dest, char* source); /* user supplied function */ int split_tokens(char* str, char* delims, int expect, char* tokens[]); /*==================== awk-like BEGIN processing ===================*/ int begin(char* dest, char* source) /* user supplied function */ { int k = 3; /* loop control*/ /* initialize totals to zeros */ for (k = 0; k < 3; k++) { totals[k] = 0.0; } return 1; /* by default write nothing to stdout at start */ } /*====================== per-record processing =======================*/ int process(char* dest, char* source) /* 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 */ /* split up input line into array*/ word_count = split_tokens(source, " \t", 5, words); /* word_count should be 5 ... check and flag error if necessary */ if (word_count != 5) { strcpy(dest, source); /*--- by default copy source -> dest */ return 99; } /*--- accumulate totals */ totals[QTY] = totals[QTY] + atof(words[3]); totals[VALUE] = totals[VALUE] + (atof(words[3]) * atof(words[4]) ); totals[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(dest, temp); /*--- by default copy source -> dest */ return 0; /*--- by default cause dest to go to stdout */ } /*================== awk-like END processing =======================*/ int finish(char* dest, char* source) /* user supplied function */ { char temp[81]; /*--- format data line */ sprintf(temp, "Total QTY and VALUE %9.2f %9.2f\nITEMS=%1.0f\n\n", totals[QTY], totals[VALUE], totals[COUNT]); /*--- arrange to display/print */ strcat(dest, "======================================================\n"); strcat(dest, temp); return 0; } /* ============= 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); } /* ---- 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; } /* ================ format header lines =================== */ int do_header(char* heading) { /*--- format heading line */ sprintf(heading, "\f\n\n%-5s %-5s %-20s %5s %7s %7s\n", "Cust#", "Inv#", "Inventory Item", "Qty", "Price", "Value"); /*--- arrange to display/print */ strcat(heading, "======================================================\n"); return 0; } FILE===================================== /* busrep3.h - prototypes for busrep3 */ void do_print(char* line); int count_lines(char* line); int do_header(char* header); FILE=========================================== /* awkfilt3.c - awk-like filter program */ /* This filter program requires three functions to make it into a complete program. The three functions should be in ONE source file, sharing static global data between them if needed. In each case they should set the return value to zero to tell the main program to output whatever is in dest, and non-zero to signal that nothing is to be output. The main program is responsible for reading, writing and routing and should be absolutely standard. It is intended that the contents of dest will not be arbitrarily cleared ... that is to say that it MAY be used to build output incrementally during several function calls ... the contents only get written to stdout when a zero is returned to main by one of the three functions int begin(char* dest, char* src); This function is called ONCE prior to reading stdin. When called, the contents of dest are irrelevant, it is provided to enable data to be passed back to main. If this function returns zero (normal) then main() writes the contents of dest to standard output. If this function returns non-zero then nothing is written to stdout. The variable src is initialised to '\0', and it probably not useful but it is provided now to facilitate possible future use. int process(char* dest, char* source); This function is called once for every input record. The input record is pointed to by source. Default processing is to move the contents of source to dest and return zero to cause the record to be written to stdout. However, there is no need for the contents of dest to bear any relationship to source so that any output may be written. To suppress the writing of output return non-zero. The contents of dest are NOT cleared by the standard main line program so that dest may be used to build output incrementally, appending data during several calls, then writing it based on some application-specific condition or trigger. int finish(char* dest, char* src); This function is called ONCE prior after eof on stdin. The contents of dest are irrelevant, it is provided to enable data to be passed back to main. If this function returns zero then main() writes the contents of dest to standard output. If this function returns non-zero then nothing is written to stdout. The variable src is initialised to '\0', and it probably not useful but it is provided now to facilitate possible future use. */ #define MAXLEN 256 #include #include int begin(char* dest, char* source); /* user-supplied function */ int process(char *dest, char *source); /* user-supplied function */ int finish(char* dest, char* source); /* user-supplied function */ void do_print(char* line); /* user-supplied function */ main(void) { char input[MAXLEN] = "\0"; char output[MAXLEN] = "\0"; int err = 0; /* error flag 0 = OK */ /*--- awk-like BEGIN processing */ err = begin(output, input); /* pre-file processing */ if (!err) do_print(output); /* write output */ /*--- main processing */ gets(input); /* get first input */ while (!feof(stdin)) { err = process(output, input); /* process */ if (!err) do_print(output); /* write output */ gets(input); /* get next input */ } /*--- awk-like END processing */ input[0] = '\0'; /* reset */ err = finish(output, input); /* post-processing */ if (!err) do_print(output); /* write output */ return 0; } FILE============================= ISYS290 - C PROGRAMMING ASSIGNMENT #3 (2 weeks - 10%) ------------------------------ Write a program which produces a business report (list and total) which includes page control with headings repeated at the top of each new page. You may use the filter program (main() ) and other functions presented in class or from your previous assignments, but you are not obliged to. If you choose not to use the filter program you should ensure that the headings, detail processing and total printing are each handled in separate functions, not intermixed. The data format for the input and the report is shown below. You should test the program first using your own data. I will provide data for the final test to ensure that each student's program gets the same test for the marking. INPUT FORMAT Inventory_class three characters used to classify inventory Inventory_code five characters Inventory_description one word up to 12 characters Item_cost unit cost, values up to $999.99 QOH_start Quantity on hand at start of period, whole number 5 digits Receipts Items received into inventory during period, whole number, 5 digits Withdrawals Items withdrawn from inventory during period, whole number, 5 digits The following data items are calculated and included in the report QOH_end Quantity on hand at end of period, whole number 5 digits Value Value of the inventory at the end of the period (QOH_end * Item_cost) OUTPUT FORMAT The detail lines are listed, including the calculated items in the sequence above. Each column has a heading above, aligned to the left for the class, code and description and to the right for the numeric columns. The heading also includes the page number. The program should start a new page after printing 55 lines. The following data items should be totaled and the totals printed at the end of the job, suitably aligned under the corresponding detail columns. QOH_start, Receipts, Withdrawals, QOH_end and Value