For this assignment, your program is to read in various infix equations. For each infix equation, your program is to convert into the same equation in postfix form and then evaluate the postfix equation. An infix equation is the way equations are typically written, for example:
5 + 12 * (10 - 4) - (8 / 4 / 2)The equation is called "infix" since the operator is in between the operands it is to use. In an postfix equation, the operator comes after operands it is to use. You may have heard of postfix notation call "reverse Polish" notation. This name comes from the nationality of the philosopher who came up with prefix notation (postfix has been described as the reverse of prefix notation). The advantage of both prefix and postfix notation is that no parentheses are needed to properly express the equation as infix may need. Since there are no parentheses, the rules to evaluate the expression are simplier. The above infix equation in postfix would be:
5 12 10 4 - * + 8 4 / 2 / -
A stack has three primary operations:
These operation have elements accessed in a Last-In-First-Out order (often called LIFO). A stack works great when you need to access values in the reverse order in which they are encountered.
To implement the stack as an array, we need three pieces of data.
position: 0 1 2 3 4 5 6 7 8 9 ... value: 3 15 9 21
To perform the pop operation, first we decrement the stack point and then remove and return the value at the position indicated by the stack pointer. If we were to pop the above stack 3 times, the first value returned would be 21 (with the stack pointer equaling 3), the second value returned would be 9 (with the stack pointer equaling 2), and the third value returned would be 15 (with the stack pointer equaling 1).
To perform the top operation, you return the value at the position of the stack pointer minus one. Note that the value of the stack pointer does NOT change. If we were to perform a top operation after the above three pops were done, the top operation would return the value of 3 (3 is at position zero, which is at the stack pointer minus one). If we were to do another top operations immediately following this top operation, the value returned would still be 3.
A stack always has potential for an error. This is when the stack is empty and either a pop or top operation is performed. Thus we should added another operation to the stack, isEmpty. This operation will return true if the stack is empty and false otherwise. Your program should always check to see if the stack is empty before doing a pop or top operation.
A stack that is implemented with a static array has another potential error. This is when the stack is full and a push operation is performed. TO deal with this error, your program must use a dynamic array instead of a static array to implement the stack. When using a dynamic array, the push operation should check if the array if full before attempting to store the value in the array. If the array is not full, proceed as normal. If the array is full, allocate a new dynamic array of twice the size of the current array, copy all of the values from the current array to the new array, deallocate the current array and make the new array the one used for all of the stack operations. When your program creates the stack, the array should have 5 positions in it. Every time array is full when a push operation is performed, print a message stating "A new array is being allocated of size X for the stack." The size of the stack should change from 5 to 10 to 20 to 40 etc. whenever the array gets filled.
5 + 12 * (10 - 4) ; 5 + 12 * (10 - 4) - (8 / 4 / 2) ; 2.25 * 3.0 + 1.25; 64/8/2; -12 - -7 ; -12--7; 12 + 4 * 5 + 7 * 21 - 4 / 2 - 8 - 2 + 5 * 3 + ( 2 * 2 * 2 * 2 * 2 ) * ( 3 + 3 + 3 + 3 ) ; 5 3 7 + / - 4 ; 5 + 3 / 7 - 4 ; 5 + 7 * 2 + 8 ; 2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2 ; 2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+(2+ (2+(2+(2+(2+(2+(2+(2+(2+2)))))))))))))))))))))))))) ; 2*(2+(2+(2*(2+(2+(2*(2+(2+(2*(2+(2+(2*(2+(2+(2*(2*(2*(2* (2+(2+(2*(2*(2*(2*(2*(2+2)))))))))))))))))))))))))) ; #
To convert an expression from infix to postfix, we must first determine if the next (valid) item in the equation is a number or an operator.
Pop the stack until either the stack is empty, the operator of ( at the top of the stack or the top value on the stack has lower precedence than the current operator. As each operator is popped from the stack, it is sent directly to the postfix equation. Then we push the current operator onto the stack.
Pop the stack until pop a open parenthesis, (. The closing parenthesis is NOT pushed on the stack. All operators that are popped (except for the open parenthesis) are sent directly to the postfix equation. If there is not an open parenthesis on the stack (i.e. you empty the stack), the equation has an error of an unmatched closing parenthesis. If this occurs, print an error message stating this occurred.
Pop the stack until it is empty, sending all popped operators to the postfix equation. The one exception is if an open parenthesis is encountered on the stack. If this happens, the equation has an error of an unmatched open parenthesis. In this case, print an error message stating this occurred. You may wish to send the ; operator to the postfix equation so you will know where the postfix equation ends.
Let us step throught the algorithm to convert the input of
5 + 12 * (10 - 4) ;into a postfix expression.
Step 1. Current item: 5 (numeric value) Stack: empty Postfix Equation: 5 Send numeric value directly to Postfix Equation. Step 2. Current item: + (operator) Stack: + Postfix Equation: 5 Since stack is empty, nothing to pop. Then push +. Step 3. Current item: 12 (numeric value) Stack: + Postfix Equation: 5 12 Send numeric value directly to Postfix Equation. Step 4. Current item: * (operator) Stack: + * Postfix Equation: 5 12 Since + has lower precedence than *, nothing to pop. Then push *. Step 5. Current item: ( (operator) Stack: + * ( Postfix Equation: 5 12 Since * has lower precedence than (, nothing to pop. Then push (. Step 6. Current item: 10 (numeric value) Stack: + * ( Postfix Equation: 5 12 10 Send numeric value directly to Postfix Equation. Step 7. Current item: - (operator) Stack: + * ( - Postfix Equation: 5 12 10 Since top of stack is (, nothing to pop. Then push -. Step 8. Current item: 4 (numeric value) Stack: + * ( - Postfix Equation: 5 12 10 4 Send numeric value directly to Postfix Equation. Step 9. Current item: ) (operator) Stack: + * Postfix Equation: 5 12 10 4 - Pop operators from the stack until ( is popped. Step 10. Current item: ; (operator) Stack: empty Postfix Equation: 5 12 10 4 - * + ; Pop operator from the stack until it is empty, then add ; to the postfix equation.If your program encounters an error while translating an infix expression into a postfix expression, print out the appropriate error message and as much of the postfix expression as has been so far created. Then clear the stack and the postfix expression. Finally restart translating an infix expresion into a postfix expression at the next item in the input. Your program will only attempt to evaluted the postfix expression if the postfix expression was created without error.
The evaluate the postfix equation of:
5 12 10 4 - * + ;We do the following:
Step 1. Current item: 5 (numeric value) Stack: 5 The numeric value is pushed onto the stack. Step 2. Current item: 12 (numeric value) Stack: 5 12 The numeric value is pushed onto the stack. Step 3. Current item: 10 (numeric value) Stack: 5 12 10 The numeric value is pushed onto the stack. Step 4. Current item: 4 (numeric value) Stack: 5 12 10 4 The numeric value is pushed onto the stack. Step 5. Current item: - (operator) Stack: 5 12 6 The numeric values of 4 and 10 are popped from the stack and the result of 10 - 4 is pushed onto the stack. Note: the first operand in the subtraction is the second value popped while the second operand is the first value popped. This is very important since x - y is not the same as y - x. Step 6. Current item: * (operator) Stack: 5 72 The numeric values of 6 and 12 are popped from the stack and the result of 12 * 6 is pushed onto the stack. Step 7. Current item: + (operator) Stack: 77 The numeric values of 72 and 5 are popped from the stack and the result of 5 + 72 is pushed onto the stack. Step 8. Current item: ; (operator) Stack: 77
class StackElem { // This class will store either a character or double data type. // The names reflect the intended usage of this class with a program // for infix to postfix equation translation and postfix equation // evaluation. // The class has two data members: // the first is an instance of an enumerated type to tell whether // the instance of the class is an operator/character or a // number/double. THis value could be undefined in case the // instance of the class is created by the default constructor. // // the second is an instance of a union that will hold either the // character value or the double value public: // create the enumerated type to determine the value stored in // the instance enum SEType {UNDEFINED, OPERATOR, NUMBER}; private: // create the union to hold either the character or the double value union SEUnion { char oper; double numb; }; // data member definition SEType et; // the instance of the enumerated type SEUnion eu; // the instance of the union public: // default constructor - type is unknown StackElem () { et = UNDEFINED; eu.oper = '\0'; eu.numb = 0.0; } // constructor to set up the instance to hold an operator StackElem (char op) { et = OPERATOR; eu.oper = op; } // constructor to set up the instance to hold a numeric value StackElem (double num) { et = NUMBER; eu.numb = num; } // a method to store an operator in the instance void setOperator(char op) { et = OPERATOR; eu.oper = op; } // a method to store a numeric value in the instance void setNumber(double num) { et = NUMBER; eu.numb = num; } // a method to return the type of value stored in the instance SEType getType() { return et; } // a method to access an operator value // This method will return true if the instance does indeed // store an operator and false otherwise // The method uses a pass-by-reference parameter to send the // operator value back to the calling code. If the instance // does not contain an operator the null character is sent // back to the calling code. bool getOperator (char &op) { if (et == OPERATOR) { op = eu.oper; return true; } else { op = '\0'; return false; } } // a method to access an operator value // This method will return the operator value if the // instance does indeed store an operator value. // Otherwise the null character is returned. char getOperator () { if (et == OPERATOR) return eu.oper; else return '\0'; } // a method to access a numeric value // This method will return true if the instance does indeed // store a numeric and false otherwise // The method uses a pass-by-reference parameter to send the // numeric value back to the calling code. If the instance // does not contain an numeric the value of 0.0 is sent // back to the calling code. bool getNumber (double &num) { if (et == NUMBER) { num = eu.numb; return true; } else { num = 0.0; return false; } } // a method to access a numeric value // This method will return the numeric value if the // instance does indeed store a numeric value. // Otherwise the value of 0.0 is returned. double getNumber () { if (et == NUMBER) return eu.numb; else return 0.0; } // This method is meant for debugging purposes. // It outputs the type and value of the instance to cout. void output () { if (et == UNDEFINED) cout << "UNDEFINED."; else if (et == OPERATOR) cout << "OPERATOR: " << eu.oper; else if (et == NUMBER) cout << "NUMBER: " << eu.numb; } };
Your program must be written using good programming style. This includes (but is not limited to) such items as:
Your program will be submitted electronically on the icarus system using the turnin command. The project name for this will be mp5. Your program will graded based on how it executes on the icarus system using the g++ compiler. Getting a program to work on another system or using another compiler does NOT mean it will work on the icarus system using the g++ compiler. Programs that do not work properly on the icarus system using the g++ compiler will lose points. Also programs that are not submitted via the turnin command will also lose points. Emailing a program is not an acceptable form of electronic submission.