The goal of this project is to practice using stacks in an algorithm.
Polish mathematician Jan Lukasiewicz invented a notation for arithmetic where the operator comes before the operands, for example + 5 3 instead of 5 + 3. The advantage of this is that the order of operation is always unambiguous without the need for parentheses (or even precedence rules). For example, 5 * 3 - 9 is written - * 5 3 9, whereas 5 * (3 - 9) is written * 5 - 3 9. In honor of its inventor (or his nationality, at any rate), this is referred to as Polish notation. (It is also called prefix notation, in contrast to normal arithmetic notation which is thus infix.)
Reverse Polish notation is similar except that the operator is put after the operands (so it is also postfix notation). The advantage is that all the operands are then known before the operator is read, if we read the string from left to right. This notation is particularly interesting for our purposes, because a stack can be used to evaluate expressions in RPN. Your task is to write a calculator that evaluates expressions entered in RPN.
In this project you will use the same GUI as in the earlier calculator example. After making the directory for this project, get the starter code for this project:
cp -r ~tvandrun/Public/cs245/proj6/* .
The starter code is identical to that of Project 2 except for the given test cases (see below).
As before, you will need to implement the method
SetUp.setUpCalculator()
,
which takes an object of some class that
implements CalculatorFace
and
attaches the other parts of your calculator to that face.
As a reminder, please note that when your submission
is graded, your setUpCalculator()
method will be
called, and it will be given an object implementing the
CalculatorFace
interface you are given, but it
will not be an instance of the ConcreteCalculatorFace
class.
ConcreteCalculatorFace
is given for your own testing
purposes.
That is why your code should not be dependent on that class,
only on the interface.
Also, the main method of SetUp
will not be called,
only the setUpCalculator()
method.
In short, the contract you need to fulfill is
WhensetUpCalculator()
is given an object implementing the interfaceCalculatorFace
, it will instantiate and attach action listeners to the given object (and instantiate any other appropriate classes, ie the "brain" or whatever you call it) so that the given object will behave like a (in this case, RPN) calculator.
One difficulty in using RPN, especially on a simulated hand-held calculator, is how to delimit the operands. The string 937+ could mean 9 + 37 or 93 + 7. In a string, this disambiguation would be done using spaces. For your calculator, you should interpret the "." button as indicating the boundary between numbers. Consequently, your calculator needs to work only on integers; division should be integer division. This also means that you don't have to worry about screen overflow or other formatting. I also won't be checking for how you handle division by zero. Additionally, the equals button is useless-- you do not need to do anything when it is pressed.
Generally this is an easier project than the previous calculator project (and easier than the next calculator project...). The emphasis is not on polishing (heh heh) the calculator's extreme cases but on using the stack. That doesn't mean, however, that you shouldn't think through what the calculator should do in unusual cases. You should. There are just fewer unusual cases.
Even though this section of the course is about data structures, you should keep thinking about object-oriented design, and especially take the things you learned in Project 2 and work to make this project's design to be better than what you did in the first calculator. I hope the feedback you received with your Project 2 grades will be helpful in that regard.
You may have heard that later in this course you will be given a project where you have to write a calculator without any ifs. See if you can reduce the number of if statements you need. (That does not mean that you should replace ifs with switches, ?: conditionals, degenerate while loops, or exception handling. It means you should try to replace ifs with polymorphism.)
You should also implement the clear button. This should reset the entire calculator. Moreover, if the user presses the operation buttons when there is not enough information in the stack, your calculator should just ignore it. You calculator should not crash in such a situation.
A few specifics (I mention these because they are things that have confused students in previous semesters):
5 . 8 . 3 - *
.
That's equivalent to the infix expression 5 * (8- 3)
Think through what the stack needs to look like at each step.
1 . 3 +
the dot
marks the boundary between 1 and 3, but there is no
dot terminating 3.
This should result in 4.
However, having an "extra" dot after 3 should also work:
1 . 3 . +
should also result in 4.
+ 5 * 2 . 3 +
should
result in 55 (that is, 52 + 3).
The first +
and the *
are ignored.
The scenarios mentioned above are tested in the given
JUnit test TestCalcRPN
.
Your submission, however, will be tested on many more
test cases.
You are encouraged to test your program not only "by hand"
(running calc.SetUp
)
but also by adding test cases to TestCalcRPN
.
Please turn in all the files you wrote or modified
(besides TestCalcRPN
)
to the turn-in directory for this project:
cp (some file) /cslab.all/ubuntu/cs245/turnin/(your user id)/proj6
DUE: 5:00 pm Monday, Nov 16.
Grading for this project will follow this approximate point breakdown (the right to make minor adjustments in point distribution is reserved):
Note the greater weight given to design and efficiency.