表达式求值 (栈) 用C++实现
1 #include <cstdio> 2 3 #include <cstdlib> 4 5 #include <cmath> 6 7 #include <stack> 8 9 #include <cstring> 10 11 using namespace std; 12 13 14 15 char Precede(char a, char b) { //判断运算符优先级 16 17 int i, j; 18 19 char Table[8][8] = { 20 21 {' ','+','-','*','/','(',')','='}, 22 23 {'+','>','>','<','<','<','>','>'}, 24 25 {'-','>','>','<','<','<','>','>'}, 26 27 {'*','>','>','>','>','<','>','>'}, 28 29 {'/','>','>','>','>','<','>','>'}, 30 31 {'(','<','<','<','<','<','=',' '}, 32 33 {')','>','>','>','>',' ','>','>'}, 34 35 {'=','<','<','<','<','<',' ','='} 36 37 }; //优先级表格 38 39 for(i=0; i<8; i++) 40 41 if(Table[0][i]==a) //寻找运算符a 42 43 break; 44 45 for(j=0; j<8; j++) //寻找运算符b 46 47 if(Table[j][0]==b) 48 49 break; 50 51 return Table[j][i]; 52 53 } 54 55 56 57 bool Calcu_temp(double a, char theta, double b, double &r) { //计算二元表达式的值 58 59 if(theta=='+') 60 61 r = a + b; 62 63 else if(theta=='-') 64 65 r = a - b; 66 67 else if(theta=='*') 68 69 r = a * b; 70 71 else { 72 73 if(fabs(b-0.0)<1e-8) //如果除数为0,返回错误信息 74 75 return false; 76 77 else 78 79 r = a / b; 80 81 } 82 83 return true; 84 85 } 86 87 88 89 bool IsOper(char ch) { //判断字符ch是否为运算符 90 91 char ptr[10] = {'+', '-', '*', '/', '(', ')', '='}; 92 93 int i; 94 95 for(i=0; i<7; i++) { 96 97 if(ch==ptr[i]) 98 99 return true; 100 101 } 102 103 return false; 104 105 } 106 107 108 109 bool Calculate(char s[], double &result) { //计算表达式的结果 110 111 char theta; 112 113 int i = 0, j, point = 0; 114 115 double a, b, r, num = 0; 116 117 stack<double> num_stack; //数字栈 118 119 stack<char> oper_stack; //运算符栈 120 121 oper_stack.push('='); 122 123 while(s[i]!='=' || oper_stack.top()!='=') { //对表达式a进行计算 124 125 if((s[i]>='0' && s[i]<='9') || s[i]=='.') { //字符是数字或者小数点 126 127 num = 0; //初始化数字为0 128 129 point = 0; //point用来标记是否出现小数点以及当前处于小数点后第x位,point==10^x 130 131 if(s[i]=='.') 132 133 point = 10; 134 135 else 136 137 num = s[i] - 48; 138 139 j = i + 1; 140 141 while(!IsOper(s[j])) { //继续往后查找并记录该数字,直到该数字结束遇到运算符为止 142 143 if(s[j]=='.') { 144 145 point = 10; 146 147 j++; 148 149 continue; 150 151 } 152 153 if(!point) //整数部分 154 155 num = num * 10 + ( s[j] - 48 ); 156 157 else { 158 159 num = num + 1.0 * ( s[j] - 48 ) / point; //小数部分 160 161 point *= 10; //小数位数后移一位 162 163 } 164 165 j++; 166 167 } 168 169 i = j; 170 171 num_stack.push(num); //将该数字压入栈中 172 173 } 174 175 else if(IsOper(s[i])) { //字符是运算符 176 177 switch(Precede(s[i],oper_stack.top())) { //该运算符和栈顶运算符进行优先级比较并做相关处理 178 179 case '<': 180 181 oper_stack.push(s[i++]); 182 183 break; 184 185 case '=': 186 187 oper_stack.pop(); 188 189 i++; 190 191 break; 192 193 case '>': 194 195 theta = oper_stack.top(); //从栈中弹出一个运算符进行计算 196 197 oper_stack.pop(); 198 199 b = num_stack.top(); //弹出两个数字,注意顺序,先弹出的数是第二个操作数 200 201 num_stack.pop(); 202 203 a = num_stack.top(); 204 205 num_stack.pop(); 206 207 if ( Calcu_temp(a, theta, b, r) ) //计算并判断是否有除数等于0的情况 208 209 num_stack.push(r); //若正常,则将结果压入栈中 210 211 else 212 213 return false; //出现除数为0的情况,返回错误信息 214 215 break; 216 217 } 218 219 } 220 221 } 222 223 result = num_stack.top(); //最后数字栈中的数即为表达式的最终结果 224 225 return true; 226 227 } 228 229 230 231 bool Check(char s[]) { //检查表达式括号是否匹配 232 233 int flag=0, i; 234 235 for(i=0; s[i]!=0; i++) { 236 237 if(s[i]=='(') 238 239 flag++; 240 241 if(s[i]==')') 242 243 flag--; 244 245 } 246 247 if(flag) 248 249 return false; 250 251 else 252 253 return true; 254 255 } 256 257 258 259 int main() { 260 261 // freopen("in.txt", "r", stdin); 262 263 int i, j; 264 265 char s1[210], s2[210]; 266 267 double result; 268 printf("\t\t表达式求值(栈)\n"); 269 printf("******************************************************************\n"); 270 printf("请输入表达式,等号不用输入:\n"); 271 272 while(gets(s1)!=NULL) { //输入表达式 273 274 if(strlen(s1)==1 && s1[0]=='0') 275 276 break; 277 278 for(i=0,j=0; s1[i]!=0; i++) { //将表达式转换为规格化的表达式,并在末尾加上“=”,保存在s2中 279 280 if(s1[i]==' ') 281 282 continue; 283 284 s2[j++] = s1[i]; 285 286 } 287 288 s2[j++] = '='; 289 290 s2[j] = '\0'; 291 292 if(Check(s2)) { //检查括号是否匹配 293 294 if(Calculate(s2, result)) //计算并检查表达式中是否出现除数为0的情况 295 296 printf("%lf\n",result); 297 298 else 299 300 printf("除数不能为0\n"); 301 302 } 303 304 else 305 306 printf("括号不匹配\n"); 307 308 } 309 310 return 0; 311 312 }