CSCI 112: Programming and Algorithms II
Program 4: Post-fix Calculator
Grading Weight: 3 (programs will have a weight between 1 - 5)



Overview:

The standard form of equations, 2 + 4, is called infix because the operator (+ in this example) is "in" the middle of the operands (2 and 4 in this example).  This form has the drawback of not being able to control the order in which the operators are applied without using parentheses.  For example, if you want 2 + 4 multiplied by 5, you have to write (2+4)*5.  While this is easy to do in a programming language, it is difficult to do on a standard calculator.

Postfix notation (also called Reverse Polish Notation or RPN) is much better suited for calculators.  In postfix notation, the operator goes after the operand.  For example, the equation 2 4 + means 2 plus 4, and the expression 2 4 + 5 * means to first apply + to 2 and 4 and then apply * to the result of 2 + 4 and 5.  The result is (2 + 4) * 5 and you didn't have to type in the "(" and ")".

Postfix calculators are easily implemented using a stack data structure.  When the user enters an operand, it is inserted on to the stack (in stacks, inserting on top of the stack is called push).  When the user enters a binary operator, the 2 operands on top of the stack are removed (popped), the operator is applied to them, and the result is pushed on to the stack.

If at the end of the input, there is one and only one operand on the stack, then the input was a valid expression and the value on the stack is the result of evaluating that expression.

This assignment is to implement an RPN calculator that can evaluate any legal expression and catch all illegal input (except numbers with so many digits that they won't fit into a double).  As soon as illegal input is encountered, print the error message (see below) and call exit(1).

Program Requirements:

Implementation:

Implement your stack from scratch using dynamic allocation.  In other words, your stack must look like a linked-list.  You may not use a stack from a library.  Create a class Node to hold the elements of the stack.  This class must be nested inside of class Dstack.

Implement your program using the following class:
class Dstack
Stack of doubles that provides at least the following functions:
push - push a new element on top of the stack
pop  -  remove and return the top element from the stack (must be able to deal with an empty stack)
~Dstack - a correct destructor
You may use whatever return types and arguments you see fit.  You may add additional functions if you need them.
Put main() in the file calc.cpp


Input:

Your program must read a single equation from standard input.   The operators are + - * / ^ (^ is power, 2 4 ^ is 2 raised to the power of 4).  Numbers can be any double number, for example 4, 4.2, .2, 0.2, 0000.233.  You can assume that the number is small enough to fit into a double variable (I won't give you a number with 200 digits).

Your program should ignore all white space (spaces, tabs, newlines).

If two numbers are in a row, there must be a space between them.  For example, 42 is the number forty-two, and 4  2 are the numbers four and two.

There do not have to be spaces between numbers and operators.  For example, 10 10+ is a legal equation.

There do not have to be spaces between two operators.  For example, 10 10 10++ is a legal equation.


Files:


Each class should have a .h file and a .cpp file (note that the filenames are all lower case):

dstack.h
dstack.cpp

In addition to the above files, you will need to turn in a file containing your main() function:

calc.cpp

Program Output:

If the input is a correct post-fix expression, your program should print the result.

For example, if the input is 10 10+, your program should output 20 followed by a newline, and nothing else (don't print any prompts or "aswer =").


Errors and Error Messages:

If the input is not a valid post-fix expression, your program should print the following to standard error:
 Error: Invalid expression.

followed by a newline (not a blank line, but a newline) and then call exit(1).

Your program must check for all types of errors (except numbers that are too large).



Hints:

The algorithm is:

while (not the end of the input)

If the next input is a number, read it and push it on the stack
If the next input is an operator, read it, pop 2 operands off of the stack, apply the operator, push the result onto the stack
When you reach the end of the input:

if there is one number on the stack, print it
else error


I suggest you implement and test the stack before you tackle the calculator aspects of the program.  You will have to write a few lines of code in main() to do this testing, but it will save you time in the long run.

You can't just use getline() or cin >> string_variable for this program because you usually don't know if an operator or an operand (a number) will be the next thing in the input stream.  You will need to use cin.peek() to look at the next character in the input.  cin.peek() returns the next character without actually reading it.  In other words, the next character you read will be the one returned by cin.peek().  If it is whitespace (space, tab, newline) you can skip it using cin.ignore().  If it is a legal operator, you can read the single character using cin >> char_variable.  If the next character is a digit, you can use cin >> double_variable to read the entire number.  cin.peek() returns EOF (which is defined as -1) if end-of-file is true.



General Requirements:

I will deduct 10 percent if your program does not compile using my Makefile on a Linux machine. Thus you must make sure to use the filenames listed below (do not capitalize your filenames), and if you are working on windows, you should compile and test your program on a Linux machine before turning it in.

We will grade your program using another program, so if your program does not work exactly as specified below you will lose points.

The first lines of all your files (.h and .cpp) must contain:


// last name, first name
// ecst_username@ecst.csuchico.edu
// 112 Program 4: RPN Calculator


Testing Your Program:

For this assignment I have provided a bash script (a program that the bash shell can execute) to automatically test your program.  Read the automatic testing instructions and download the .tar file in the tests/p4 directory.

I will test your program with additional tests not posted in the test directory.  It is a very good idea to design and implement your own set of tests.

How to turn in code:

You must turn in the following file:

calc.cpp
dstack.h
dstack.cpp

See the turn in instructions for details on how to turn in this assignment.

The turn in instructions contain details on turning in a late assignment.



Extra credit:

You will get 10 points extra credit if your program passes all the extra credit tests, and a fraction of 10 points if it passes some of the extra credit tests.  Since these are multi-character operators, you will have to modify how you read the input. 

Implement the following operators:

sqrt   calculate the square root of the previous number,  15 sqrt means the square root of 15.

cos   calculate the cosine of the previous number, 30 cos means the cosine of 30

sin    calculate the sine of the previous number, 45 sin means the sine of 45

Note: Assume the user is entering degrees.  Since the math.h functions cos() and sin() expect the angle in radians you will ahve to convert the number to radians.  Use the constant M_PI from math.h to perform the conversion.


ave   remove all the operands off the stack, calculate there average and push the result on to the stack