COSC 071: Computer Science I

Project 3
Spring 2011

Due: Wed, Mar 30 @ 5 PM
8 points

For p2, you implemented a Payment class. Two problems with the design and implementation of this class were that we used strings to represent dates and entered amounts could have been negative. For this project, we're going to eat our own dog food. (Apologies to cat lovers.) In addition to making other minor revisions to the Payment class, we are going to fix these two things.

Your first task is to implement a Date class, which consists of three integers: day, month, and year. Dates must print or output in the format MM/DD/YYYY, and the default date should be 01/01/1970, which relates to the Unix epoch.

Begin by implementing the usual constructors, accessors, observors, and print and enter methods for the Date class. (Note that Date::enter does not necessarily need to prompt the user for each data member.) Instead of implementing read and write methods, for this project, you will overload the stream insertion and stream extraction operators, which we can also use for input and output. You must also implement an overloaded relational operator for less than. (Notice that encoding dates as strings makes it impossible to make comparisons between dates that are logically correct.)

You should also declare constant methods as appropriate. Finally, the set methods must perform data-integrity checks to ensure that all values stored in the private data members are valid. The error handling scheme must implement is what I call “fail silently,” whereby the set method leaves a private data member unchanged when it is passed an invalid value. You should implement these checks only once in the appropriate set method and ensure that all execution paths that values external to the class follow reach the appropriate check. You do not have to worry about leap years, but months must have the correct number of days.

Once you have implemented and thoroughly tested the Date class, then you need to refactor the Payments class to use the Date class. This will not only include replacing the string representation of the date of the payment, but it will also include changing any method that uses Payment::date. In addition to these changes, you need to overload the stream insertion and stream extraction operators for the Payment class and implement a data-integrity check in Payment::setAmount that fails silently when its parameter is negative.

The application that you write using the Payment and Date classes will perform the same tasks as that for p2, but rather than entering three payments from the keyboard, the main function should read three payments from the file named “payments.in”. (Note that you can not use the current version of Payment::read because it reads only one payment from a file, rather than multiple payments. You'll use the overloaded stream extraction operator for this purpose.) After reading the payments, the main function should print their information to the console, and print the total of the three payments. The main function should also ensure that the payments in the file are ordered properly, meaning that each payment should have a higher number and later date than the payment before it. If either occurs, then the main function should print an error message and keep processing payments.

As with p2, the file format for storing payments in a file consists of four fields. The first is the number, the second is the date, the third is the payee, and the fourth is the amount. Note that now we are reading and writing information to and from files the order of this information is critically important. Each is separated by one space. As an example, payments.in might look like:

350 02/04/2011 Tombs 17.95
351 02/05/2011 Wisemiller's 9.75
352 02/07/2011 Starbucks 2.95
Once you've implemented and tested the Date and Payment classes, you should be able to read and output the first payment with the following main function:
int main()
{
  Payment payment1;
  ifstream fin( "payments.in" );
  fin >> payment1; // call to overloaded stream extraction operator Payment
  payment1.print();
  return 0;
} //
which should produce the output:
  Number: 350
  Date: 02/04/2011
  Payee: Tombs
  Amount: $17.95

A transcript of a sample run of the complete project appears below with the user's input typeset in bold:

seva% g++ p3.cc
seva% a.out
Payment 1:
  Number: 350
  Date: 02/04/2011
  Payee: Tombs
  Amount: $17.95

Payment 2:
  Number: 351
  Date: 02/05/2011
  Payee: Wisemiller's
  Amount: $9.75

Payment 3:
  Number: 352
  Date: 02/05/2011
  Payee: Starbucks
  Amount: $2.95

Total: $88.18
seva%

As you know, a critical approach to developing software systems is decomposing a programming task into smaller, manageable pieces. The classes and methods required to solve a problem give us a natural way to decompose problems. Begin by designing the class definition. What are the private data members' names? What are their types?

From there, design the public interface. What methods are necessary? What are their names? What parameters do they have? What return types do they have? Should they be constant methods?

Once you have designed the public interface, type the class definition. Start with the code in template.cc and add the class construct. Compile and run, correcting any syntax errors.

Add each of the method declarations. Compile and run, correcting any syntax errors.

Once you have a syntactically correct class definition, start implementing the class methods. Implement the default constructor. Declare a Date object in the main function. Compile and run. Then implement a print method. It doesn't have to print an entire date in its correct format. Start with printing, say, the month. Compile and run. Modify the main function and call the print method for the payment object. Compile and run. Continue in this fashion until you have finished the implementation of the Date class.

The approach of stepwise refinement and incremental development minimizes errors and helps manage the complexity of software development. If you start each step with a working program and you add a few lines of code, if you make a mistake, then it mostly likely involves the last few lines you typed. On the other hand, if you start by entering your 300-line program all at once and compiling, you will be overwhelmed by the number of compiler errors. Even experienced programmers don't do this.

For this project, you need to write doc comments for the Date class. Documentation comments are discussed in Section 4.19 of the book, and we'll discuss them in class. Use a class comment with @author and @version tags. Document each method with a method comment with @param and @return tags, as appropriate.

Getting Started

The first thing you want to do is make a copy of your project from p2. To do this, at the seva prompt, type:

cp p2.cc p3.cc
It is going to take us a couple of lectures to get through all of the material required for this project. However, you should get started implementing the Date class and refactoring the Payment class based on what you currently know. If you do this, then extending these classes based on the new material should be easier and more obvious.

As you know, the projects are getting more complicated, so get started on the project now. Do not be fooled by a deadline that seems far, far away. Also, if your implementation of the Payment class from p2 is a little shaky, try to fix it using the clarity that comes only after you've submitted an assignment. If that doesn't work, come see me.

Instructions for Submission

At the top of the file containing your source code (i.e., the file containing the C++ instructions), place the following header comment above the Doc comment documenting your class with the appropriate modifications:
//
// COSC-071 Project 3
// Name: <your name>
// E-mail: <e-mail address>
// Instructor: Maloof
// Spring 2011
//
// In accordance with the class policies and Georgetown's Honor Code,
// I certify that, with the exceptions of the lecture notes and those
// items noted below, I have neither given nor received any assistance
// on this project.
//

When you are ready to submit your program for grading, use the submit program, just like you did for p2. Both submit.jar and the file containing your program should be in the same directory. You can confirm this by listing the files in your home directory:

seva% ls
p3.cc    submit.jar
You may see other files from previous assignments in your home directory, but p3.cc and submit.jar should be among them.

This assignment's label is p3. Assuming the file you want to submit is p3.cc, then to submit you enter the command

seva% java -jar submit.jar -a p3 -f p3.cc
Make sure you submit the file containing your program's source, not its executable code; that is, do not submit a.out.

Once you've submitted your project, it is a good idea to keep a copy on seva, which preserves the modification date and time and ensures that you will have a backup copy of your project. If we lose your project or submit breaks, then we will need to look at the modification date and time of your project to ensure that you submitted it before it was due.

The TAs who will be grading your projects this semester are listed on the main page. You must submit your project before 5 PM on the due date.