But this is not the case for infix expressions! e.g. 9 + (2 3) * 8 Two approaches to evaluate an infix expression: Use two stacks within one scan. Convert to equivalent postfix expression and then call the infix expression evaluator.
Rank of Expression
Binary operators only. Evaluates an infix expression based on rank. 1 for any operand -1 for +, -, *, /, %, ^ 0 for (, ) Cumulative rank: sum of the ranks of individual terms.
cumulative 101010010101101 rank: 2^7^6+(3 2*4)%5
Infix-to-Postfix Conversion
During the scan of an expression:
An operand is immediately written to the output string. No need to maintain an operand stack.
Operator stack
Stores operators and left-parenthesis symbols as soon as they appear. Manages the order of precedence and associativity of operators. Handles subexpressions.
Example 1
The stack temporally stores operators awaiting their right-hand-side operand. a+b*c
* has higher priority than + add to the stack Operator Stack:
* + a b c * +
Postfix string:
Example 2
Use the stack to handle operators with same or lower precedence. a*b /c+d
* has the same priority as / pop * and write it to the postfix string before adding / to the stack. / has higher priority than +
Operator Stack:
+ * / a b * c / d +
Postfix string:
Example 3
Use precedence values to handle ^ (right associative). input precedence 4 when ^ is the input. stack precedence 3 when ^ resides on the stack. a^b^c
2nd ^ has precedence 4 but 1st ^ has only 3 2nd ^ goes to operator stack (so it will be popped before 1st ^)
Operator Stack:
^ ^ a b c ^
Postfix string:
Example 4
Two precedence values for left parenthese ( : input precedence 5 which is higher than that of any operator.
(all operators on the stack must remain because a new subexpression begins.)
stack precedence
a*(b+c)
+ ( * a b c +
+ * / % ^ ( )
1 2 4 5 0
1 2 3 -1 0
-1 -1 -1 0 0
An Example
3 * (4 2 ^ 5) + 6
Operator stack postfix
( [-1] * [2] 34
contd
Pop ( * [2] 3425^3 * (4 2 ^ 5) + 6 + [1] 3425^-* + [1] 3425^-*6
3425^-*6+
infix2Postfix contd
private: string infixExpression; // the infix expression to convert string postfixExpression; // built to contain the postfix equivalent of infixExpression stack<expressionSymbol> operatorStack; // stack of expressionSymbol objects void outputHigherOrEqual(const expressionSymbol& op); // the expressionSymbol object op holds the current // symbol. pop the stack and output as long as the symbol // on the top of the stack has a precedence >= that of // the current operator bool isOperator(char ch) const; // is ch one of '+','-','*','/','%','^' };
void infix2Postfix::outputHigherOrEqual(const expressionSymbol& op) { expressionSymbol op2; while(!operatorStack.empty() && (op2 = operatorStack.top()) >= op) { operatorStack.pop(); postfixExpression += op2.getOp(); postfixExpression += ' '; } }
Processing an Operand
// process until end of the expression for (i=0; i < infixExpression.length(); i++) { ch = infixExpression[i]; // ******** process an operand ******** // an operand is a single digit non-negative integer if (isdigit(ch)) { // just add operand to output expression, followed by // a blank postfixExpression += ch; postfixExpression += ' '; // rank of an operand is 1, accumulated rank // must be 1 rank++; if (rank > 1) throw expressionError("infix2Postfix: Operator expected"); }
Processing an Operator
// ********* process an operator or '(' ********** else if (isOperator(ch) || ch == '(') { // rank of an operator is -1. rank of '(' is 0. // accumulated rank should be 0 if (ch != '(') rank--; if (rank < 0) throw expressionError("infix2Postfix: Operand expected"); else { // output the operators on the stack with higher // or equal precedence. push the current operator // on the stack op = expressionSymbol(ch); outputHigherOrEqual(op); operatorStack.push(op); } }
Finish Processing
// outside the for loop if (rank != 1) throw expressionError("infix2Postfix: Operand expected"); else { // flush operator stack and complete expression evaluation. // if find left parenthesis, a right parenthesis is missing while (!operatorStack.empty()) { op = operatorStack.top(); operatorStack.pop(); if (op.getOp() == lParen) throw expressionError("infix2Postfix: Missing ')'"); else { postfixExpression += op.getOp(); postfixExpression += ' '; } } } return postfixExpression; }
try { // convert to postfix iexp.setInfixExp(infixExp); postfixExp = iexp.postfix(); // output the postfix expression cout << "The postfix form is " << postfixExp << endl; // use pexp to evaluate the postfix expression pexp.setPostfixExp(postfixExp); cout << "Value of the expression = " << pexp.evaluate() << endl << endl; } // catch an exception and output the error catch (const expressionError& ee) { cout << ee.what() << endl << endl; } // input another expression cout << "Enter an infix expression: "; getline(cin, infixExp); } }