|
| 1 | +/** |
| 2 | + * Given an infix expression, convert it to postfix. Consider usual operator precedence. |
| 3 | + * Consider only following operands in your arsenal. |
| 4 | + * +, -, * , /, ^(power) |
| 5 | + * Operands are only alphabets --> 'a '-->'z' and 'A'-->'Z' |
| 6 | + * Another assumption is operand is a single char. |
| 7 | + */ |
| 8 | + |
| 9 | +#include <iostream> |
| 10 | +#include <stack.h> |
| 11 | +#include <string> |
| 12 | + |
| 13 | +// all utility and main functions declared first |
| 14 | +/** |
| 15 | + * isOperator- Determines if input char is operator |
| 16 | + * @param c - char |
| 17 | + * @return - true or false |
| 18 | + */ |
| 19 | +bool isOperator( char c ); |
| 20 | + |
| 21 | +/** |
| 22 | + * isOperand Determines if input char is operand |
| 23 | + * @param c - char |
| 24 | + * @return true or false. |
| 25 | + */ |
| 26 | +bool isOperand( char c ); |
| 27 | + |
| 28 | + |
| 29 | +/** |
| 30 | + * getOperatorWeight returns an integer weight of the operator |
| 31 | + * @param c - An operator |
| 32 | + * @return Weight of operator , larger is more precedence |
| 33 | + */ |
| 34 | +int getOperatorWeight(char c); |
| 35 | + |
| 36 | + |
| 37 | +/** |
| 38 | + * isRightAssociative -Determines if operator is right associative. |
| 39 | + * @param c operator |
| 40 | + * @return returns true if operator is right associative |
| 41 | + * |
| 42 | + * Associativity only comes to picture when both operators have same weight |
| 43 | + * Example ^ is right associative ( ^ represents power of) |
| 44 | + * 5 ^ 4 ^ 3 ^ 2 = 5 ^ ( 4 ^ ( 3 ^ 2 ) ) |
| 45 | + * where as 7 − 4 + 2 (7 − 4) + 2 = 5 or 7 − (4 + 2) = 1 |
| 46 | + */ |
| 47 | +bool isRightAssociative(char c); |
| 48 | + |
| 49 | +/** |
| 50 | + * [hasHigherPrecedence] compare op1 and op2 based on precedence |
| 51 | + * @param op1 operaror 1 |
| 52 | + * @param op2 operator 2 |
| 53 | + * @return return true if precedence(op1) > precedence(op2), else false |
| 54 | + */ |
| 55 | +bool hasHigherPrecedence(char op1, char op2); |
| 56 | + |
| 57 | +/** |
| 58 | + * [infixToPostfix - converts infix expr to postfix expr |
| 59 | + * @param expression - infix expre |
| 60 | + * @return postfix expr |
| 61 | + */ |
| 62 | +std::string infixToPostfix( std::string expression ); |
| 63 | + |
| 64 | + |
| 65 | +//check if c is an operator |
| 66 | +bool isOperator( char c ) |
| 67 | +{ |
| 68 | + if ( c == '+' || c == '-' || c == '*' || c == '/' || c == '^') { |
| 69 | + return true; |
| 70 | + } |
| 71 | + return false; |
| 72 | +} |
| 73 | + |
| 74 | +//check if c is a valid operand defined in comments. |
| 75 | +bool isOperand( char c ) |
| 76 | +{ |
| 77 | + if ( c >= 'a' && c <= 'z' ) return true; |
| 78 | + if ( c >= 'A' && c <= 'Z' ) return true; |
| 79 | + return false; |
| 80 | +} |
| 81 | + |
| 82 | +//returns precedence weight of the char c. |
| 83 | +// more weight higher precedence. |
| 84 | +int getOperatorWeight( char c ) |
| 85 | +{ |
| 86 | + int weight; |
| 87 | + switch(c) { |
| 88 | + case '+': |
| 89 | + case '-': |
| 90 | + weight = 1; |
| 91 | + break; |
| 92 | + case '*': |
| 93 | + case '/': |
| 94 | + weight = 2; |
| 95 | + break; |
| 96 | + case '^': |
| 97 | + weight = 3; |
| 98 | + break; |
| 99 | + default: |
| 100 | + weight = -1; |
| 101 | + } |
| 102 | + return weight; |
| 103 | +} |
| 104 | + |
| 105 | + |
| 106 | +// is operator right associative? |
| 107 | +bool isRightAssociative( char op ) |
| 108 | +{ |
| 109 | + if ( op == '^') return true; |
| 110 | + return false; |
| 111 | +} |
| 112 | + |
| 113 | +bool hasHigherPrecedence( char op1, char op2 ) |
| 114 | +{ |
| 115 | + // get weight of the operators |
| 116 | + int w1 = getOperatorWeight(op1); |
| 117 | + int w2 = getOperatorWeight(op2); |
| 118 | + |
| 119 | + // If both operators weigh same, return true if operators are |
| 120 | + // left associative, return false if right associative. |
| 121 | + if ( w1 == w2 ) { |
| 122 | + if ( isRightAssociative(op1) ) { |
| 123 | + return false; |
| 124 | + } |
| 125 | + return true; |
| 126 | + } |
| 127 | + return w1 > w2 ? true : false; |
| 128 | +} |
| 129 | + |
| 130 | +// final function to convert infix to postix operator. |
| 131 | + |
| 132 | +std::string infixToPostFix(std::string expr) |
| 133 | +{ |
| 134 | + bool errorDetected = false; |
| 135 | + algo::Stack<char> operatorStack; |
| 136 | + std::string postFixExpr = ""; |
| 137 | + |
| 138 | + //scanning input infix expr left to right char by char |
| 139 | + for ( char c : expr ) { |
| 140 | + |
| 141 | + // char is delimiter, continue |
| 142 | + if ( c == ',' || c == ' ') { |
| 143 | + continue; |
| 144 | + } |
| 145 | + |
| 146 | + //if character is an operand |
| 147 | + else if ( isOperand(c) ) { |
| 148 | + postFixExpr += c; |
| 149 | + } |
| 150 | + |
| 151 | + //if character is operator |
| 152 | + else if ( isOperator(c) ) { |
| 153 | + //if stack is not empty pop the stack back and compare precedence. |
| 154 | + //if higher precedence perform operation. |
| 155 | + while ( !operatorStack.empty() && operatorStack.top() != '(' && |
| 156 | + hasHigherPrecedence(operatorStack.top(), c) ) { |
| 157 | + postFixExpr += operatorStack.top(); |
| 158 | + operatorStack.pop(); |
| 159 | + } |
| 160 | + operatorStack.push(c); |
| 161 | + } |
| 162 | + |
| 163 | + else if( c == '(' ) { |
| 164 | + operatorStack.push(c); |
| 165 | + } |
| 166 | + |
| 167 | + else if( c == ')' ) { |
| 168 | + while( !operatorStack.empty() && operatorStack.top() != '(' ) { |
| 169 | + postFixExpr += operatorStack.top(); |
| 170 | + operatorStack.pop(); |
| 171 | + } |
| 172 | + operatorStack.pop(); |
| 173 | + } |
| 174 | + |
| 175 | + else { |
| 176 | + std::cout << " ERROR An invalid operator/operand detected\n"; |
| 177 | + errorDetected = true; |
| 178 | + break; |
| 179 | + } |
| 180 | + } |
| 181 | + if (errorDetected) { |
| 182 | + return "INVALID EXPR!"; |
| 183 | + } |
| 184 | + |
| 185 | + while( !operatorStack.empty() ) { |
| 186 | + postFixExpr += operatorStack.top(); |
| 187 | + operatorStack.pop(); |
| 188 | + } |
| 189 | + return postFixExpr; |
| 190 | +} |
| 191 | + |
| 192 | + |
| 193 | +int main() |
| 194 | +{ |
| 195 | + std::string expr; |
| 196 | + std::cout << "Provide an expression such that :" |
| 197 | + << "1. Expression shoule be parenthesis valid.\n" |
| 198 | + << "2. Operators should contain +, -, /, *, ^\n" |
| 199 | + << "3. Operands should contain A-Z or a-z \n" |
| 200 | + << "Your expression is :"; |
| 201 | + std::getline(std::cin, expr); |
| 202 | + std::cout << "Corresponding postfix expression of the express - " |
| 203 | + << expr |
| 204 | + << " is :" << infixToPostFix(expr) << std::endl; |
| 205 | + return 0; |
| 206 | +} |
0 commit comments