栈计算中缀表达式
1 #include<iostream> 2 #include<stack> 3 #include<ctype.h> 4 #include<math.h> 5 #include<string> 6 using namespace std; 7 8 static char s1[] = "2*(3+5)+7/1-4\0"; 9 static char s2[] = "(1+2^3!-4)*(5!-(6-(7-(89-0!))))\0"; 10 11 // 运算符优先级数组 12 const char pri[9][9] = { 13 {'>', '>', '<', '<', '<', '<', '<', '>', '>'}, 14 {'>', '>', '<', '<', '<', '<', '<', '>', '>'}, 15 {'>', '>', '>', '>', '<', '<', '<', '>', '>'}, 16 {'>', '>', '>', '>', '<', '<', '<', '>', '>'}, 17 {'>', '>', '>', '>', '>', '<', '<', '>', '>'}, 18 {'>', '>', '>', '>', '>', '>', ' ', '>', '>'}, 19 {'<', '<', '<', '<', '<', '<', '<', '=', ' '}, 20 {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 21 {'<', '<', '<', '<', '<', '<', '<', ' ', '='}, 22 }; 23 24 // 运算符映射 25 int symbolIndex(char str) 26 { 27 if ('+' == str) 28 return 0; 29 else if ('-' == str) 30 return 1; 31 else if ('*' == str) 32 return 2; 33 else if ('/' == str) 34 return 3; 35 else if ('^' == str) 36 return 4; 37 else if ('!' == str) 38 return 5; 39 else if ('(' == str) 40 return 6; 41 else if (')' == str) 42 return 7; 43 else if ('\0' == str) 44 return 8; 45 } 46 47 // 逻辑映射 48 int logicIndex(char str) 49 { 50 if('<' == str) 51 return 1; 52 else if('=' == str) 53 return 2; 54 else if ('>' == str) 55 return 3; 56 return -1; 57 } 58 59 // 数学计算 60 float calculation(float i, char j, float k) 61 { 62 if ('!' == j) 63 { 64 float factorial = 1; 65 for (int a = 1; a <= i; ++a) 66 { 67 factorial *= a; 68 } 69 return factorial; 70 } 71 else if ('+' == j) 72 { 73 return k + i; 74 } 75 else if ('-' == j) 76 { 77 return k - i; 78 } 79 else if ('*' == j) 80 { 81 return k * i; 82 } 83 else if ('/' == j) 84 { 85 return k / i; 86 } 87 else if ('^' == j) 88 { 89 return pow(k, i); 90 } 91 } 92 93 // 计算表达式 94 float calculationStr(char* S) 95 { 96 int index = 0; 97 stack<char> symbolStack; // 运算符栈 98 stack<float> numStack; // 运算数栈 99 symbolStack.push('\0'); 100 101 while(!symbolStack.empty()) 102 { 103 if(isalnum(S[index])) 104 { 105 string str = ""; 106 while(isalnum(S[index])) 107 { 108 str += S[index++]; 109 } 110 numStack.push(atof(str.c_str())); 111 } 112 else 113 { 114 int i = symbolIndex(symbolStack.top()); 115 int j = symbolIndex(S[index]); 116 char logic = pri[i][j]; 117 switch(logicIndex(logic)) 118 { 119 case 1: // 当前运算符优先级大于栈顶时直接入栈 120 symbolStack.push(S[index++]); 121 break; 122 case 2: // 当前运算符优先级相等时去左括号和'/0'符 123 symbolStack.pop(); 124 index++; 125 break; 126 case 3: // 当前运算符优先级小于栈顶时从栈中取数字并计算,将所得结果压入栈中 127 char op = symbolStack.top(); 128 symbolStack.pop(); 129 if('!' == op) 130 { 131 float num1 = numStack.top(); 132 numStack.pop(); 133 numStack.push(calculation(num1, op, 0)); 134 } 135 else 136 { 137 float num1 = numStack.top(); 138 numStack.pop(); 139 float num2 = numStack.top(); 140 numStack.pop(); 141 numStack.push(calculation(num1, op, num2)); 142 } 143 break; 144 } 145 } 146 } 147 148 return numStack.top(); 149 } 150 151 int main() 152 { 153 cout<<calculationStr(s1)<<endl; 154 cout<<calculationStr(s2)<<endl; 155 }
优化点:
1. 取运算符映射和逻辑映射写法过于丑陋;
2. 从字符串中读取极可能多的数字的方式略显笨拙
3. 字符串遍历时应摒弃index++的方式
祝我无坚不摧,祝我百毒不侵,祝我狼心狗肺,祝我逍遥快活。