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 <iostream>
 #include <iomanip>
 #include <fstream>
 #include <cctype>


 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.