Lab 6 Working with Files and Objects Introduction ============ You've been working very hard! In this lab, we will step back a little and work through some examples of using file streams and objects. Not to worry though, I promise this will still be a challenging and rewarding lead in to the next leg of the journey! Lab 6.1 (Guided) Selling more than 3 things ============================================ The owners of Trillium Inc. have decided to replace their old cash register system. Their old system was severely limited, so they are a bit wary of programmers. Also, their cashiers have complained that the old system is too complicated to use. They want something simple and menu driven. Finally, the owners have decided that it would be nice if the cash register could keep a record of its transactions. You know, that way they can track sales and make sure they have the right amount of money on hand. For the first part of this, we are going to create a simple menu system for the register. It will have 2 modes, transaction entry and journal review. We will be storing the cash register history in a file. The first step is to produce a stub of this program in order to test out the menu system. Enter and execute the following code, come back when you have it running. --begin register.cpp -- #include #include #include #include using namespace std; //function prototypes int menu(); void newTransaction(); void writeLineItem(string item, int qty, double cost) void endTransaction(); void readReceipts(); int main(void) { int choice; //drive the menu do { choice = menu(); //get the choice switch(choice) { case 1: //new transaction newTransaction(); break; case 2: //print journal readReceipts(); break; } } while(choice !=3); return 0; } // displays the menu and returns a valid result int menu() { int choice; cout << " Cash Register Menu" << endl; do { cout << "1. Enter a new transaction." << endl; cout << "2. Review journal of transactions." << endl; cout << "3. Exit" << endl; cout << endl << "Choice? "; //discard non integer input while (!isdigit(cin.peek())) cin.get(); cin >> choice; if(choice < 1 || choice > 3) { cout << "Invalid selection. Please try again." << endl; } } while(choice < 1 || choice > 3); return choice; } void newTransaction() { cout << "newTransaction" << endl; } void writeLineItem(string item, int qty, double cost) { cout << "writeLineItem" << endl; } void endTransaction() { cout << "endTransaction" << endl; } void readReceipts() { cout << "readReceipts" << endl; } --end register.cpp -- Notice how all the above functions are stubs. This allows us to test the program and see what functions are getting executed. The next step is to implement the cashier's interface. What the cashiers have decided is that they want to enter an item, the quantity of the item, and its cost. They want to repeat this until they enter a blank item. Then they want a simple display indicating the total amount due on the receipt. Also, if we keep in mind that we want to write all this to a journal, we can go ahead and call our writeLineItem function as well as our endTransaction function. We do all this in the newTransaction function. Modify newTransaction so that it reads as follows: void newTransaction() { string item; int qty; double cost; double total = 0.0; //go until we get an empty item do { //clear out cin cin.clear(); cin.ignore(1000, '\n'); cout << "Item (blank to end): "; getline(cin, item); if(!item.length()) continue; cout << "Qty: "; cin >> qty; cout << "Price: "; cin >> cost; //add to the journal writeLineItem(item, qty, cost); //add to the total total += qty * cost; } while(item.length()); cout << "Total Due: $" << fixed << setprecision(2) << total << endl; //mark the end of the transaction endTransaction(); } Test your program again to make sure it is working. We now turn our attention to the journal file. We have to declare the format that we are going to store transactions in. Because item names can contain spaces, we will put each field on a line by itself. Thus the format goes: item name quantity cost With a blank line separating transactions. Because we are journaling, we want to open the file in append mode. The two key operations are "writeLineItem" and "endTransaction". Modify these two functions so they read as below: void writeLineItem(string item, int qty, double cost) { ofstream file; //the journal file //append a single item to the file, one field at a time file.open("registerTape", ios::app); file << item << endl; file << qty << endl; file << cost << endl; file.close(); } void endTransaction() { ofstream file; //the journal file //append a single blank line to the file. This ends the transaction. file.open("registerTape", ios::app); file << endl; file.close(); } Test this program out now. Note that it creates a file named "registerTape" in your directory. cat registerTape and verify that this writes the correct format. You should enter a few transactions using your program to test it. Now we only need to provide a way of running the reports. To do this, we start with the following modification: void readReceipts() { ifstream file; //the journal file; string item; int qty; double cost, lineCost; double total = 0.0; //open the file and read to the end file.open("registerTape"); while(!file.eof()) { //get the item getline(file, item); //handle break in transactions if(!item.length()){ //display the transaction total and reset if(total > 0) cout << setw(32) << total << endl << endl; total = 0.0; continue; } //get the other fields file >> qty >> cost; //consume newline if(file.peek() == '\n') file.get(); //do a little math stuff lineCost = qty * cost; total += lineCost; //print a user friendly display cout << fixed << setprecision(2) << setw(10) << item << ' ' << setw(5) << qty << ' ' << setw(7) << cost << ' ' << setw(7) << lineCost << endl; } file.close(); } Run your program a few times, enter some transactions, and verify that they show up in the reports. Now as a final exercise, cleanup the output of readReceipts to make it look better. Add some headers and some dollar signs. This is a subjective thing, so I want you to be creative. Have fun practicing your formatting skills and make a display you can be proud of. When you are done, create a script file containing your complete code, your run, and a cat of your registerTape file. Lab 6.2 Computing Your Grade ============================= Imagine, for a moment, that you are in a CS class who's final grade is computed by means of weighted averages divided into the following categories: Exams: 40% Guided Lab Assignments: 10% Self Completed Lab Assignments: 30% Assignments: 20% Given your present circumstances, you shouldn't have to tax your imagination too heavily! Now, suppose that you want to keep track of your grade. A great way to do this would be with a program which keeps records in a file. Since that is the topic of this lab, I think you can see where we are headed! So now, here's your task. You want to design and implement a program which does the following: 1. Presents the user with the choice of entering a new grade or reviewing old grades. 2. Stores the grades in a single file. 3. Shows a grade report listing all of your scores (along with the category of each) and displays the averages for each category, and the weighted final average. The design of the interface and the file are completely up to you this time! Be sure to include a description of your file format in the pseudocode. Also, include examples of what your user interface will look like. HINTS: - enum is your friend. There are only so many categories. - You can use a similar strategy to that which was developed in the guided part of lab 6.