/* Program to read a binary file of restaurant menu items to make a check for a customer. Input: Binary file "anx17-02.bin" containing one menu_item structure (see below) per line in the input file. Terminal entry of menu item numbers until EOF. Warning: no check for illegal terminal input. Output: A file "prntfile" containing a check showing listed item names, descriptions, and prices, and a bill total. This program illustrates the use of the fseek() function to locate a record in a file of many identical entries. */ typedef struct { char name[31]; /* item name */ char description[51]; /* item description */ int price; /* price in cents */ } menu_item; #include #include #include /* for tolower() */ #include "lst10-7.c" /* for file_open function */ void display_instructions_and_headings(FILE *printfile); void process_order(FILE *infile, FILE *printfile); main() { FILE *infile, *printfile; infile = file_open("anx17-02.bin", "rb"); /* open file for binary input */ printfile = file_open("prntfile", "w"); /* for printer output */ display_instructions_and_headings(printfile); process_order(infile, printfile); fclose(infile); fclose(printfile); printf("Order complete - see file \"prntfile\"\n"); } void process_order(FILE *infile, FILE *printfile) { menu_item item; int status; long cost=0; /* Total order cost: long as order may exceed $327.67 */ long item_cost; /* cost of one item in cents */ int item_no, quantity; char answer; /* Now process a customer order. Ask the number of the menu items, and for each one, look up the entry in the infile. Item 1 will be at the start of this file, so it will have offset zero from the start. That is, each entry is offset by its item number minus 1 from the start. To locate an item, this offset must be multiplied by the length of each item, that is, the sizeof a menu_item. The order will be complete when zero is entered for an item number. */ while ( printf("Enter an item number and quantity, or EOF when finished: ") , /* <<<--- a comma operator */ status = scanf("%d %d", &item_no, &quantity) , status == 2 && item_no > 0 ) { status = fseek(infile, (sizeof item) * (long)(item_no - 1), SEEK_SET); /* Status is 0 if fseek succeeded. Now test that and try to input an item from the seek'd position. */ if (status != 0 || fread(&item, sizeof item, 1, infile) != 1) { fprintf(stderr, "Cannot locate item in file.\n"); } else { /* Here we have an item - process it. */ printf("Order for %d %s. Correct (Y/N)? ", quantity, item.name); scanf(" %c", &answer); answer = tolower(answer); /* Turn capitals to lower case. */ if (answer == 'y') { printf("Adding item to order.\n"); item_cost = (long)item.price * quantity; cost += item_cost; fprintf( printfile, "%3d %-20.20s %-40.40s %6.2f\n", quantity, item.name, item.description, (float)item_cost / 100 /* cost in dollars */ ); } else { printf("Item cancelled.\n"); } } } /* Now finalise the order */ fprintf(printfile, "\nTotal:%70.2f\n\f", (float)cost / 100); } void display_instructions_and_headings(FILE *printfile) { /* Outputs instructions to the user and prints the order heading */ fprintf( printfile, "\t\tRestaurant Order\n\n" "Number\tName\t\t Description\t\t\t\tCost\n\n" ); printf( "Restaurant Menu Selector\n" "Enter the number of a menu item and then the quantity.\n" "Repeat for all menu items, then enter EOF\n\n" ); }