Introduction:
This project builds on Projects 1 and 2 and aims to give you experience with (a) constructing classes and (b) reading from files. For Project 3, you will write a program that performs a task that is more or less identical to the task performed in Project 2. The only differences are that you will use a class to organize your program better and your program will read from a file rather than from standard input.
The Expression class:
For this project you will define and use a class called Expression; the interface of this class should be defined in a file expression.h and the implementation should be defined in a file expression.cc. Objects belonging to the Expression class will be used by your program to represent valid arithmetic expressions. A valid arithmetic expression is as defined in the handout for Project 2. Given a valid expression, there are two operations we would like to perform on the expression: (a) add to the expression a number and (b) multiply the expression by a number. These operations should be defined as member functions add and multiply belonging to the Expression class. For example, suppose that euler is an object belonging to the Expression class. Then, the statement
euler.add(5);
adds the number 5 to the expression represented by euler. Similarly, the statement
euler.multiply(7);
multiplies the expression represented by euler by 7.
The task of building the Expression class is complicated by the fact that operator precedence needs to be respected. For example, suppose that euler represents the expression
5 + 4
It is tempting to think that this expression can simply be represented by its value, 9. However, if the next operation performed on euler is
euler.multiply(2);
then the user wants euler to represent the expression 5 + 4 * 2 and not (5 + 4)*2. Thus, if only the value of the expression is used to represent the expression, then there is not enough information to perform subsequent operations correctly.
Based on this example and our past experience with Projects 1 and 2, it seems reasonable to use the following three variables to represent an expression: (a) myOperator: this represents the right most + operator in the expression, (b) myLeftOperand: this represents the value of the expression to the left of the right most + operator, (c) myRightOperator: this represents the value of the expression to the right of the right most + operator. These three variables should be declared appropriately in the private portion of the Expression class. In case an expression does not have a + operator in it, then myOperator should have the value ' ' to indicate the absence of a + operator, myLeftOperand will have the value of the expression, and myRightOperand will have the value 0.
For example, if euler is an object belonging to the Expression class, that represents 5 + 4 * 2, then the three private variables of euler mentioned above will have the following values: myOperator equals '+', myLeftOperand equals 5, and myRightOperand equals 8.
Besides the member functions add and multiply mentioned above, the Expression class should contain an appropriate constructor and a function called value that returns the value of the expression being represented. For example, if euler represents that expression 5 + 4 * 2 then the statement
cout << euler.value() << endl;
should print the value 13.
Besides the 4 functions mentioned above, you are free to add any other public member functions to the Expression class that you think are useful to a user of the class. Similarly, you are free to add any other private data members to the Expression class that you think are useful. However, you will be graded on the design choices you make in constructing the Expression class.
Input and Output:
Your program should start by asking the user for the name of a file.
If the user types quit then your program should terminate
immediately.
If the user types anything else, your program should interpret that
as the name of a file that the user wants your program to read from.
For example, in response to the program-prompt, if the user types
data, then your program should read from a file called data.
Your program should attempt to read an expression from the user-specified
file and should produce the following output:
(a) the contents of the file and
(b) the value of the expression if the expression is valid or an appropriate
error message if the expression is not valid.
For example, if the file data contains:
1 * 0
345678 +
Then your program should produce as output:
345678 +
1 * 0
The value of this expression is 345678
The expression is:
Similarly, if the file data contains an invalid expression, then, after producing the complete expression as output, your program should report the appropriate error.
After your program has processed the expression in the file specified by the user, it should prompt the user for another file. Thus, this process will go on until the user types quit.
Organization of your program:
Functions such as getOperand, getOperator, printOperatorError, and printOperandError, that you wrote for Project 2 should be reused in Project 3. Instead of performing arithmetic computations in the main function explicitly, you should have the main function call the functions add and multiply. In this way the task of maintaining and updating valid expressions is transferred to a large extent from the main function to the Expression class.
What to turn in:
Turn in a single 3.5'' Macintosh formatted disk with a three files called project3.cpp, expression.cc, and expression.h. The grader will only examine files with these names; files with other names will be ignored. You should also make sure that there is nothing else on your diskette; points will be deducted for any other files on your diskette.
If your program is on a PC formatted diskette, there is no need to reformat it for a Macintosh since Power Macintosh computers in MLH ITC can read PC formatted diskettes also. However, if you are a PC user you should make sure that your program compiles and executes within the CodeWarrior environment as well. All programs, independent of their origins, have to compile and execute within the CodeWarrior environment.
Clearly label your diskette by writing your name, section number, and the project number on it. In addition turn in a printout of your program. Place the printout and the diskette in a folder and label the folder clearly. This will substantially ease the grader's task and will make it easier to keep track of projects.
A final word:
Instructions and advice from Project 1 and Project 2 handouts related to making your program more readable, still apply. Please don't wait till April 10th to start thinking about the project. As always, the TAs and I will be glad to help. Have a pleasant spring break!