1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 #include <cstdio> 5 #include <cctype> 6 #include <sstream> 7 using namespace std; 8 9 template<typename T> 10 class Stack 11 { 12 private: 13 T *base; //栈底指针 14 int top; //栈顶 15 int stackSize; //栈容量 16 public: 17 Stack(int m = 16); //构造函数 18 ~Stack() { 19 delete[]base; top = 0; stackSize = 0; 20 } 21 void Push(T x); //入栈 22 T Pop(); //出栈 23 T Top(); //获取栈顶元素 24 bool StackEmpty(); //测栈空 25 void ClearStack(); //清空栈 26 void StackTop(); //返回栈顶指针 27 void Capacity(); //返回栈容量 28 void StackTranverse(); //显示栈中元素(遍历) 29 }; 30 31 template<typename T> 32 void Stack<T>::Capacity() 33 { 34 return stackSize; 35 } 36 37 template<typename T> 38 Stack<T>::Stack(int m) 39 { 40 base = new T[m]; 41 if (!base) { 42 cout << "创建栈失败,退出!\n"; exit(1); 43 } 44 stackSize = m; top = -1; //栈顶(top = -1)为最底单元地址的下一处 45 } 46 47 template<typename T> 48 void Stack<T>::Push(T x) 49 { 50 if (top == stackSize - 1) throw "栈满,无法入栈"; 51 base[++top] = x; 52 //cout << "top: " << top << endl; 53 } 54 55 template<typename T> 56 T Stack<T>::Pop() 57 { 58 T x; 59 if (top == -1) throw "栈空,不能出栈"; 60 x = base[top--]; 61 //cout << "top: " << top << endl; 62 return x; 63 } 64 65 template<typename T> 66 T Stack<T>::Top() 67 { 68 if (top == -1) throw "栈空,栈顶无元素"; 69 //cout << "top: " << top << endl; 70 return base[top]; 71 } 72 73 template<typename T> 74 bool Stack<T>::StackEmpty() 75 { 76 if (top == -1) return true; 77 return false; 78 } 79 80 template<typename T> 81 void Stack<T>::ClearStack() 82 { 83 top = -1; 84 } 85 86 //返回栈顶指针 87 template<typename T> 88 void Stack<T>::StackTop() 89 { 90 cout << "栈顶 top = " << top; 91 } 92 93 template<typename T> 94 void Stack<T>::StackTranverse() 95 { 96 int i = top; 97 while (i >= 0) { 98 cout << base[i--] << ‘\t‘; 99 } 100 cout << endl; 101 } 102 103 104 const int EXP_MAX = 50 + 10; 105 double Pow(double x, int n); 106 long long facI(int b); 107 108 //运算符优先级比较---栈顶优先级大,要出栈进行运算,栈顶小,当前运算符入栈 109 char Precede(char t1, char t2) //t1--栈顶, t2--当前运算符 110 { 111 switch (t2) 112 { 113 case ‘+‘: 114 case ‘-‘: if (t1 == ‘(‘ || t1 == ‘=‘) return ‘<‘; //栈顶运算符小,当前运算符直接入栈 115 else return ‘>‘; 116 case ‘*‘: 117 case ‘/‘: 118 case ‘%‘: if (t1 == ‘*‘ || t1 == ‘/‘ || t1 == ‘%‘ || t1 == ‘^‘ || t1 == ‘!‘ || t1 == ‘)‘) return ‘>‘; 119 else return ‘<‘; //如果t1是以上运算符,就 > , 否则就小 120 case ‘^‘: if (t1 == ‘)‘ || t1 == ‘!‘) return ‘>‘; 121 else return ‘<‘; 122 case ‘!‘: if (t1 == ‘)‘ || t1 == ‘!‘) return ‘>‘; //大于除了 , = 之外的常规运算符 123 else return ‘<‘; 124 case ‘(‘: if (t1 == ‘)‘) { 125 cout << "ERROR !\n"; exit(0); 126 } 127 else return ‘<‘; 128 case ‘)‘: switch (t1) { 129 case ‘(‘: return ‘=‘; 130 case ‘=‘: cout << "ERROR2" << endl; exit(0); 131 default: return ‘>‘; 132 } 133 134 case ‘=‘: switch (t1) { 135 case ‘=‘: return ‘=‘; 136 case ‘(‘: cout << "ERROR2" << endl; exit(0); 137 default: return ‘>‘; 138 } 139 140 141 default: cout << "Opera error !\n"; break; 142 } 143 } 144 145 //判断c是否是运算符 146 bool isOper(char c) 147 { 148 switch (c) { 149 case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘: 150 case ‘%‘: case ‘^‘: case ‘!‘: 151 case ‘(‘: case ‘)‘: case ‘=‘: return true; 152 default: return false; 153 } 154 } 155 156 //实施一次运算 --- 二元运算符 157 double Operate(double a, char op, double b) 158 { 159 switch (op) { 160 case ‘+‘: return a + b; 161 case ‘-‘: return a - b; 162 case ‘*‘: return a * b; 163 case ‘/‘: return a / b; 164 case ‘%‘: return (int)a % (int)b; 165 case ‘^‘: return Pow(a, b); 166 default: 167 cerr << "Opera wrong !\n"; exit(1); 168 } 169 } 170 //重载实施一次一元运算符运算 171 double Operate(double a, char op) 172 { 173 switch (op) { 174 case ‘!‘: return facI(a); 175 default: 176 cout << "Opera wrong !\n"; exit(1); 177 } 178 } 179 180 //将起始于p的子串解析为数值,并存入操作数栈 181 void readNumber(char *&p, Stack<double> &stk) 182 { 183 stk.Push((double)(*p - ‘0‘)); //当前数位对应的数位进栈 184 while (isdigit(*(++p))) { 185 stk.Push(stk.Pop() * 10 + (*p - ‘0‘)); 186 } 187 if (‘.‘ != *p) return; 188 float fraction = 1; //否则,意味着还有小数部分,操作数解析完成 189 while (isdigit(*(++p))) { 190 stk.Push(stk.Pop() + (*p - ‘0‘)*(fraction /= 10)); 191 } 192 } 193 194 //计算阶乘 195 long long facI(int b) { //计算阶乘 196 long long result = 1; 197 for (int i = 1; i <= b; i++) 198 result *= i; 199 return result; 200 } 201 202 double Pow(double x, int n) //计算乘方 203 { 204 if (n == 0) return 1; 205 if (n == 1) return x; 206 if (n % 2 == 0) return Pow(x * x, n / 2); 207 else 208 return Pow(x * x, n / 2) * x; 209 } 210 211 //中缀表达式求值 212 double evaluate(char *exp) 213 { 214 Stack<char> optr(EXP_MAX); //运算符栈 215 Stack<double> opnd(EXP_MAX); //运算数栈 216 char op; 217 218 double pnd1, pnd2; 219 // char opstack; //用于opcur--当前运算符, opstack--栈顶运算符 220 // char conv[EXP_MAX]; //存放浮点数字符串 221 222 optr.Push(‘=‘); //将结束标志=推入栈中 223 224 // opcur = *exp++; //当前元素 225 // opstack = optr.Top(); //栈顶元素 226 227 while (*exp != ‘=‘ || optr.Top() != ‘=‘) //当前元素遇到 =, 或者到栈顶结束符 = 228 { 229 if (isdigit(*exp)) { 230 readNumber(exp, opnd); 231 } 232 else { 233 switch (Precede(optr.Top(), *exp)) 234 { 235 case ‘<‘: 236 optr.Push(*exp); exp++; 237 break; 238 case ‘=‘: //遇到 ‘)‘,将栈顶的‘(‘弹出,并*exp++ 239 optr.Pop(); exp++; break; 240 case ‘>‘: 241 op = optr.Pop(); 242 if (op == ‘!‘) { 243 pnd1 = opnd.Pop(); //若属于一元运算符 244 opnd.Push(Operate(pnd1, op)); //实施一元运算 245 } 246 else { //对其他二元运算符 247 pnd2 = opnd.Pop(), pnd1 = opnd.Pop(); //后出栈的在运算符前:pnd1 op pnd2 248 opnd.Push(Operate(pnd1, op, pnd2)); 249 } 250 break; 251 } 252 } 253 } 254 return opnd.Pop(); //返回最后计算出的数 255 } 256 257 //转换成后缀表达式 258 void CreatePostExp(const char *exp, char *&postexp) 259 { 260 Stack<char> op(EXP_MAX); //定义一个操作数栈 261 op.Push(‘=‘); //=是结束标志 262 // cout << "Exp : " << exp << endl; 263 264 // unsigned int j; 265 // unsigned int len = strlen(exp); 266 // //只有一个数的情况 267 // for (unsigned j = 0; j < len && (isdigit(exp[j]) || exp[j] == ‘.‘); j++) { 268 // postexp[j] = exp[j]; 269 // } 270 // if (j == len) { 271 // postexp[j] = ‘ ‘; 272 // return; 273 // } 274 275 // for (unsigned int i = 0; i < len; i++) postexp[i] = ‘0‘; 276 277 int k = 0; 278 while (*exp) 279 { 280 if (isdigit(*exp) || *exp == ‘.‘) { 281 postexp[k++] = *exp++; 282 } 283 if (isOper(*exp)) { 284 postexp[k++] = ‘ ‘; //计算表达式时,‘ ‘可以作为一组数字结束的标志 285 switch (Precede(op.Top(), *exp)) { 286 case ‘<‘: //栈顶小,当前运算符进操作符栈 287 op.Push(*exp); exp++; break; 288 case ‘=‘: //遇到右括号,弹出左括号,*exp++ 289 op.Pop(); exp++; break; 290 case ‘>‘: //遇到栈顶运算符优先级高的,则出栈,添加到后缀表达式的后面 291 postexp[k++] = op.Pop(); break; 292 } 293 } 294 postexp[k] = ‘\0‘; //填上结束标志 295 } 296 cout << "后缀表示为: " << postexp << endl; 297 } 298 299 //计算后缀表达试 300 double evaluateRPN(const char *postexp) 301 { 302 Stack<double> ans(EXP_MAX); //操作数栈 303 304 string tmp; //用来转换数字 305 306 // int len = strlen(postexp) 307 // for (int i = 0; i < len; i++) 308 while (*postexp != ‘\0‘) //末尾有结束标志 309 { 310 if (isdigit(*postexp) || *postexp == ‘.‘) { 311 tmp.push_back(*postexp); postexp++; 312 } 313 else if (*postexp == ‘ ‘) { 314 if (!tmp.empty()) { 315 double dtmp; istringstream ss(tmp); ss >> dtmp; //将tmp转换为double型数据 316 ans.Push(dtmp); tmp.clear(); //将数push到栈顶 317 } 318 postexp++; 319 } 320 else if (isOper(*postexp)) { 321 double opnd1 = 0, opnd2 = 0; 322 switch (*postexp) 323 { 324 case ‘!‘: //对于一元运算符 325 opnd1 = ans.Pop(); 326 ans.Push(Operate(opnd1, *postexp)); //实施一元运算 327 postexp++; break; 328 default: //其他二元运算符 329 opnd2 = ans.Pop(), opnd1 = ans.Pop(); 330 ans.Push(Operate(opnd1, *postexp, opnd2)); 331 postexp++; break; 332 } 333 } 334 } 335 return ans.Pop(); 336 337 } 338 339 int main() 340 { 341 //int i; 342 char exp[EXP_MAX] = "(2.2+5)+4*(5-3.1)="; 343 344 char *postexp; 345 postexp = new char[20]; 346 *postexp = ‘\0‘; 347 //char c; 348 double v1; 349 int choice; 350 char pause; 351 352 do 353 {//显示主菜单 354 cout << "1-创建表达式\n"; 355 cout << "2-表达式求值\n"; 356 cout << "3-求后缀表达式\n"; 357 cout << "4-后缀表达式求值\n"; 358 cout << "5-显示表达式\n"; 359 cout << "6-退出\n"; 360 cout << "Enter choice:"; 361 cin >> choice; 362 switch (choice) 363 { 364 case 1://创建表达式 365 cout << "请输入表达式,以=结束" << endl; 366 cin >> exp; 367 cin.get(pause); 368 system("pause"); 369 break; 370 case 2://表达式求值 371 v1 = evaluate(exp); 372 cout << exp; 373 cout << v1 << endl; 374 cin.get(pause); 375 system("pause"); 376 break; 377 case 3://求后缀表达式 378 CreatePostExp(exp, postexp); 379 cin.get(pause); 380 system("pause"); 381 break; 382 case 4://后缀表达式求值 383 v1 = evaluateRPN(postexp); 384 cout << postexp << "=" << v1 << endl; 385 cin.get(pause); 386 system("pause"); 387 break; 388 case 5:// 显示表达式 389 cout << endl; 390 cout << "已创建的表达式为:"; 391 cout << exp << endl; 392 if (strlen(postexp)) 393 { 394 cout << "后缀表达式为:"; 395 cout << postexp << endl; 396 } 397 cin.get(pause); 398 system("pause"); 399 break; 400 case 6://退出 401 cout << "结束运行,Bye-Bye!" << endl; 402 break; 403 default:// 404 cout << "Invalid choice\n"; 405 break; 406 } 407 } while (choice != 6); 408 409 return 0; 410 }//end main
测试:
时间: 2024-10-16 01:35:02