Calculator
In this assignment you will implement a simple Reverse Polish Notation
calculator using a simple "stack". This calculator supports only
integer arithmetic and the four basic operations (addition,
subtraction, multiplication, integer division).
Recall that an RPN (Reverse Polish Notation) calculator is one which
does not use parenthesis nor an equal sign. It's the standard adopted
by most Hewlett Packard calculators, so if you have one of those,
you'll feel right at home.
Let's start with an example: suppose you want to compute the result of
(2 - 3) * (2 + 3 * (5 + 3) / 4)
How would a person do it? We all do it by evaluating the
innermost parentheizied expressions first. In this case, there are
two parenthesized expressions of "equal importance:" the (2 -
3) at the beginning and the (5 + 3). Either one of these
can be evaluated first without contradicting the operator precedence
rules of arithmetic: multiplication and division before addition and
subtraction, unless you use parenthesis to force addition and
subtraction to be executed first.
An RPN calculator evaluates the sample expression above the say way a
human does, but it's up to the human to enter the sub-expressions in
the correct order. In other words, an RPN calculator will not
parse the expression. You have to parse it yourself to figure
out what to evaluate first. Thus, if I were to use my 21-year-old HP
41 CV to compute the sample expression above, I'd have to punch 2, 3,
-, 5, 3, +, 4, /, 3, *, 2, +, *, in that order, separated by presses
of the ENTER key.
Now, how does my HP 41 CV know what to do with those numbers and
operations? How are then stored? The answer to all these questions
lies in the use of a stack.
I covered stacks in handout 2 and will be covering them again in more
detail in lecture. Here, I'll just use one to show how the sample
expression above is evaluated.
If you refer to the figure at right, you'll see that every time I
enter a number, that number is pushed onto the top of the stack. What
may be a little confusing at first is what happens when I enter one of
the operations. What happens in that case is that the stack is popped
twice, to retrieve the numbers to operate on, then the operation
is performed on them, and finally the result is pushed back onto the
top of the stack. As a result, it looks as though the stack was popped
only once. As the saying goes, looks can be deceiving.
Now you're ready to tackle your programming project. Your task is to
write a C++ program which (a) uses an array (of fixed size) to
implement a stack and, using that, (b) simulates an RPN
calculator. Don't worry about implementing anything but the four
arithmetic operations (+, -, *, /), on integers only. Ignore the
problem of integer division. If you have to divide 2 by 5, for
example, go ahead and let it return 0. You should be careful, however,
to recognize the situations when the stack is empty or when it's
full. You don't want to pop from an empty stack or push onto a full
stack; it's not good for your health.
In addition, your program must output the entire array after every
input. Here's the actual output of my own solution to this
problem (with an array of size 3) when I tried to evaluate the
expression 2 * (3 + 5) by entering 2, 3, 5, +, *, - in that order:
Hello... I simulate a simple RPN calculator.
Would you like to try me? [y/n] y
Please enter the expression you want to evaluate,
one number or operation per line.
2
0
0
2 <--- top
3
0
3 <--- top
2
5
The stack is now full.
5 <--- top
3
2
+
5
8 <--- top
2
*
5
8
16 <--- top
-
The stack is empty. Cannot continue.
Notice that I entered an extra - after the expression was
evaluated. That was obviously a mistake (intentional, so that I could
explain it here) and the program caught it by printing a `stack empty'
error. What happened, of course, was that after the expression was
evaluated completely, only a single item was available on the stack
(namely, 16, the result). Thus, as the program tried to perform the -
operation, it tried to pop the stack twice. The first time was fine
(the 16 was popped), but now the stack was empty and couldn't be
popped again.
Your program should perform error checking in a fashion similar to
mine. It should detect when the stack is full or empty and should
print an error message and exit when an attempt is made to push onto
the stack if it's full or pop from it when it's empty. It should also
print the array as I did, indented so as to make it easy to read, and
it should indicate the top of the stack as I did.
In the example above, I used an array of size 3. Your program should
use an array of size 5, instead. It should be written in a modular
fashion, namely, with functions performing groups of related actions,
instead of having one large main(). Remember to name your
variables and functions appropriately and to use the coding standards
posted on the course web page.
Finally, at the end of this assignment you'll find a piece of code for
everyone to use (it's available on its own to download from the course
web page so you don't need to type it yourself). It contains the error
codes I defined and it also shows the function that parses the input
to find out if the input is an operator (+, -, *, /) or a number
(positive or negative). It's not perfect, (If you enter 5-
together, it will interpret the input as negative 5, but 5+ gives you
an error. If you enter +5, it also gives you an error.) but it
suffices for this task. This function calls on two other functions to
return its result:
- int processOperator(const char op)
- void processOperand(const int value)
You must implement these functions, for they are the ones which really
do the job.
Starting Code
You may download this as a starting point: calc.cc
Hints
- Be sure you understand stacks before you begin. What is "push"?
What is "pop?"
- Don't change the function signatures for processOperator
and processOperand.
- Remember that an "operand" is, in this case, an int, and the
"operator" is '+', '-', '*', or '/'
- A good maximum size for the stack is 20. Extra credit is available
if you make the stack grow when needed.
- The stack should be stored as a global array, and a global int to
say how much of the array is currently being used.
- You'll certainly want a function that prints out the current
state of the stack.