Introduction:
This is the second of the 4 programming projects that you are required to complete for this class. This project builds on Project 1 and so as a starting point you should either use your code for Project 1 or use the solution posted on the course page. The main differences between this project and Project 1 are as follows:
The goal of this programming project is to give you some practice with the following: (a) char data type, (b) using classes other than the string class, (c) writing a program composed of several functions, (d) using functions that return objects, and (e) checking for and responding to errors in the input.
Input:
As in Project 1, the input to your program is expected to be an
arithmetic expression.
However, for this project, there is no guarantee that the user will type
a valid arithmetic expression.
The user may make all kinds of errors while entering input.
For example, the user may type a strange character, or the user may type
an incomplete expression (that is, the expression might end with an operator),
or the user may type two operands consecutively or
two operators consecutively.
Here are 4 examples of input that do not constitute valid arithmetic
expressions.
Each example is shown in a separate line.
3 + 3 +
3 - 8 + 2 10 * 11
3 - + 2 * 11
3+ 8 plus 9 * 8
In the above example, the first line is in error because of ``strange''
characters in the input; the second line is in error because the expression
is incomplete; the third line is in error because of two operands immediately
following each other; the fourth line is in error because of two operators
immediately following each other.
Your program should read the input that the user types and if the input
is indeed a valid arithmetic expression, your program should produce as output
the value of the expression.
If, on the other hand, the input is not a valid expression, then your program
should produce an appropriate error message.
Later in this handout, you will read more about error messages.
As in Project 1, an arithmetic expression can only
include non-negative integers as operands and the operators + and *.
Furthermore, no parentheses are allowed in arithmetic expressions.
Operators and operands in a valid expression may or may not be separated by white spaces.
For example, the operator * might immediately follow the operand
89876587 as in the following example.
11 * 24567534*3+ 89876587*91111191111 * 1 * 8 + 8
The user will end the input by typing CTRL-D.
In Project 1, you could assume that the arithmetic expression in the input evaluates to an integer that is not too ``large''. This assumption cannot be made for Project 2! In fact, for this project the operands in an arithmetic expression may be arbitrarily large (that is, they may contain arbitrarily many digits). The immediate implication of this is that you cannot use the int or the long int data types to store the operands. Instead you will use the BigInt class.
Reading Input:
You may have realised by reading the above description that it is no longer possible to read operands as integers and operators as strings. Instead the input has to be read character by character while keeping a lookout for possible errors. In particular you will have to write two separate functions for reading input, as described below:
It is possible that while reading input, the function getOperand() encounters an error in the input. In this case, the function should abandon its task and return a value to the calling function that signals an error. You can read more details on error handling in the next section.
The two functions described above will be repeatedly called to get operands and operators from the input. Thus, instead of simply reading an operand from the input (as you might have done in the solution to Project 1) as follows:
cin >> num1;
for this project, you will use a statement such as:
num1 = getOperand();
Handling Errors:
As mentioned in the above section, the two functions getOperand and getOperator might encounter errors in the input as they are reading it. It is the responsibility of these functions to report the error back to the calling function. Examples of errors that the function getOperand() might encounter are as follows:
In a similar manner, the function getOperator() should return appropriate codes for the errors it encounters. For example, getOperator() could return the codes '1', '2', and so on corresponding to the different errors it encounters. Since a valid operator is '+' or '*', a value such as '1' or '2' returned by the function will be appropriately interpreted as an error signal.
A comment about the organization of your program might be appropriate here. Rather than have cout-statements for printing error messages all over your program, you should define a single function that is responsible for printing all the error messages. This function should be called repeatedly with appropriate arguments to print various error messages.
What is the BigInt class?
BigInt is a class created by the author of our textbook Owen Astrachan. The author describes it in Chapter 8 (pages 419-423). At this point we are not interested in how this class was created; we only want to use it. The purpose of this class is to allow us to use arbitrarily large integers in our programs. Recall that using int or long int data type restricts us to use integers with at most 10 digits. The BigInt class has been implemented so that the arithmetic operators that we use with int or long int variables can be used in a similar manner with objects of the BigInt class. Some examples might make this notion clearer.
BigInt x;In the first line above, an object called x belonging to the BigInt class is constructed. This is done by a call to the default constructor in the BigInt class. The constructed object x is automatically initialized to 0 by the default constructor. In the second line, the integer constant 100 is assigned to x.x = 100;
BigInt x("87942347965173");In the first line above, an object called x belonging to the BigInt class is constructed. This is done by a call to a constructor in the BigInt class that takes a string as a parameter. The object x is initialized to the integer 87942347965173 when it is constructed. The second line just demonstrates that we can use BigInt objects in assignment statements just as we would use int or long int objects.x = x*x;
What to turn in:
Turn in a single 3.5'' Macintosh formatted disk with a single file called project2.cpp that contains your C++ program. Make sure that there is nothing else 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.
A final word:
Instructions and advice from Project 1 handout related to making your program more readable, still applies. This programming project is much more complicated than Project 1. Please start thinking about it right away! As always, the TAs and I will be glad to help.