表达式计算 控制台
1 #include <iostream> 2 #include <string> 3 #include <cmath> 4 #include <cstring> 5 #include <cstdio> 6 #include <cctype> 7 #include <sstream> 8 #include <windows.h> 9 using namespace std; 10 11 void welcome(); //欢迎模块 12 void play_mp3(char *ps); //播放音乐 13 void Pos(int x, int y) { //设置放置位置 14 COORD p; 15 p.X = y;p.Y = x; 16 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p); 17 } 18 19 void welcome() { 20 char pause; 21 HANDLE console; 22 console = GetStdHandle(STD_OUTPUT_HANDLE); 23 char mp[] = "F:\\KuGou\\薛之谦_绅士.mp3"; 24 play_mp3(mp); 25 Pos(7,33); 26 SetConsoleTextAttribute(console, 15); 27 cout << " Welcome To \n"; 28 Pos(9,31); 29 cout << "↖RAT IN A MAZE↗\n"; 30 Pos(11,31); 31 cout << "by 一念永恒, 2016\n"; 32 Pos(13, 0); 33 SetConsoleTextAttribute(console, 11); 34 cout << "加载ing...\t"; 35 for(int i = 0; i<101; ++i) 36 { 37 printf("%2.0f%%", i/100.0 * 100 ); 38 Sleep(10); 39 printf("\b\b\b"); 40 } 41 SetConsoleTextAttribute(console, 11); 42 cout << endl; 43 cout << "===============================按回车键进入游戏=========================================\n"; 44 cin.get(pause); 45 system("cls"); 46 } 47 48 void play_mp3(char *ps) // 歌曲的名字 49 { 50 char str[100] = "play "; 51 strcat(str,ps); 52 mciSendString(str,NULL,0,NULL); 53 } 54 55 template<typename T> 56 class Stack 57 { 58 private: 59 T *base; //栈底指针 60 int top; //栈顶 61 int stackSize; //栈容量 62 public: 63 Stack(int m = 16); //构造函数 64 ~Stack() { 65 delete[]base; top = 0; stackSize = 0; 66 } 67 void Push(T x); //入栈 68 T Pop(); //出栈 69 T Top(); //获取栈顶元素 70 bool StackEmpty(); //测栈空 71 void ClearStack(); //清空栈 72 int StackTop(); //返回栈顶指针 73 int getElem(int index);//返回栈顶下的一个元素 74 void Capacity(); //返回栈容量 75 void StackTranverse(); //显示栈中元素(遍历) 76 }; 77 78 template<typename T> 79 int Stack<T>::getElem(int index) 80 { 81 return base[index - 1]; 82 } 83 84 template<typename T> 85 void Stack<T>::Capacity() 86 { 87 return stackSize; 88 } 89 90 template<typename T> 91 Stack<T>::Stack(int m) 92 { 93 base = new T[m]; 94 if (!base) { 95 cout << "创建栈失败,退出!\n"; exit(1); 96 } 97 stackSize = m; top = -1; //栈顶(top = -1)为最底单元地址的下一处 98 } 99 100 template<typename T> 101 void Stack<T>::Push(T x) 102 { 103 if (top == stackSize - 1) throw "栈满,无法入栈"; 104 base[++top] = x; 105 //cout << "top: " << top << endl; 106 } 107 108 template<typename T> 109 T Stack<T>::Pop() 110 { 111 T x; 112 if (top == -1) throw "栈空,不能出栈"; 113 x = base[top--]; 114 //cout << "top: " << top << endl; 115 return x; 116 } 117 118 template<typename T> 119 T Stack<T>::Top() 120 { 121 if (top == -1) throw "栈空,栈顶无元素"; 122 //cout << "top: " << top << endl; 123 return base[top]; 124 } 125 126 template<typename T> 127 bool Stack<T>::StackEmpty() 128 { 129 if (top == -1) return true; 130 return false; 131 } 132 133 template<typename T> 134 void Stack<T>::ClearStack() 135 { 136 top = -1; 137 } 138 139 //返回栈顶指针 140 template<typename T> 141 int Stack<T>::StackTop() 142 { 143 return top; 144 } 145 146 template<typename T> 147 void Stack<T>::StackTranverse() 148 { 149 int i = top; 150 while (i >= 0) { 151 cout << base[i--] << '\t'; 152 } 153 cout << endl; 154 } 155 156 const int EXP_MAX = 50 + 10; 157 double Pow(double x, int n); 158 long long facI(int b); 159 160 //运算符优先级比较---栈顶优先级大,要出栈进行运算,栈顶小,当前运算符入栈 161 char Precede(char t1, char t2) //t1--栈顶, t2--当前运算符 162 { 163 switch (t2) 164 { 165 case '+': 166 case '-': if (t1 == '(' || t1 == '=') return '<'; //栈顶运算符小,当前运算符直接入栈 167 else return '>'; 168 case '*': 169 case '/': 170 case '%': if (t1 == '*' || t1 == '/' || t1 == '%' || t1 == '^' || t1 == '!' || t1 == ')') return '>'; 171 else return '<'; //如果t1是以上运算符,就 > , 否则就小 172 case '^': if (t1 == ')' || t1 == '!') return '>'; 173 else return '<'; 174 case '!': if (t1 == ')' || t1 == '!') return '>'; //大于除了 , = 之外的常规运算符 175 else return '<'; 176 case '~': if (t1 == ')' || t1 == '~') return '>'; //大于除了 , = 之外的常规运算符 177 else return '<'; 178 case '(': if (t1 == ')') { 179 throw "ERROR: ')(', 括号匹配错误 --- 应该为 () ! \n"; //抛出异常 180 } 181 else return '<'; 182 case ')': switch (t1) { 183 case '(': return '='; 184 case '=': throw "ERROR2: =) , 表达式未完全\n"; 185 default: return '>'; 186 } 187 188 case '=': switch (t1) { 189 case '=': return '='; 190 case '(': throw "ERROR3: (= , 表达式未完全\n"; 191 default: return '>'; 192 } 193 default: throw "Opera error 无 '=' !\n"; 194 } 195 } 196 197 //判断c是否是运算符 198 bool isOper(char c) 199 { 200 switch (c) { 201 case '+': case '-': case '*': case '/': 202 case '%': case '^': case '!': case '~': 203 case '(': case ')': case '=': return true; 204 default: return false; 205 } 206 } 207 208 //实施一次运算 --- 二元运算符 209 double Operate(double a, char op, double b) 210 { 211 switch (op) { 212 case '+': return a + b; 213 case '-': return a - b; 214 case '*': return a * b; 215 case '/': if (b == 0) { 216 cout << "表达式出错 a % b, b 不等于0\n"; 217 exit(1); 218 } 219 return a / b; 220 case '%': if (b == 0) { 221 cout << "表达式出错 a % b, b 不等于0\n"; 222 exit(1); 223 } 224 if ( (b - (int)b >= 1e-10) || (a - (int)a >= 1e-10)) { 225 cout << "求余两边数不能为小数\n"; exit(2); 226 } 227 return (int)a % (int)b; 228 case '^': if (b - (int)b >= 1e-10) { 229 cout << "指数不能为小数\n"; exit(2); 230 } 231 return pow(a, b); 232 default: 233 cerr << "Opera wrong !\n"; exit(1); 234 } 235 } 236 //重载实施一次一元运算符运算 237 double Operate(double a, char op) 238 { 239 switch (op) { 240 case '!': return facI(a); 241 case '~': return -a; 242 case '-': return -a; 243 default: 244 cout << "Opera wrong !\n"; exit(1); 245 } 246 } 247 248 //将起始于p的子串解析为数值,并存入操作数栈 249 void readNumber(char *&p, Stack<double> &stk) 250 { 251 stk.Push((double)(*p - '0')); //当前数位对应的数位进栈 252 while (isdigit(*(++p))) { 253 stk.Push(stk.Pop() * 10 + (*p - '0')); 254 } 255 if ('.' != *p) return; 256 float fraction = 1; //否则,意味着还有小数部分,操作数解析完成 257 while (isdigit(*(++p))) { 258 stk.Push(stk.Pop() + (*p - '0')*(fraction /= 10)); 259 } 260 } 261 262 //计算阶乘 263 long long facI(int b) { //计算阶乘 264 long long result = 1; 265 for (int i = 1; i <= b; i++) 266 result *= i; 267 return result; 268 } 269 270 double Pow(double x, int n) //计算乘方 271 { 272 if (n == 0) return 1; 273 if (n == 1) return x; 274 if (n % 2 == 0) return Pow(x * x, n / 2); 275 else 276 return Pow(x * x, n / 2) * x; 277 } 278 279 //中缀表达式求值 280 double evaluate(char *exp) 281 { 282 Stack<char> optr(EXP_MAX); //运算符栈 283 Stack<double> opnd(EXP_MAX); //运算数栈 284 char op; 285 286 double pnd1, pnd2; 287 // char opstack; //用于opcur--当前运算符, opstack--栈顶运算符 288 // char conv[EXP_MAX]; //存放浮点数字符串 289 290 optr.Push('='); //将结束标志=推入栈中 291 292 // opcur = *exp++; //当前元素 293 // opstack = optr.Top(); //栈顶元素 294 295 while (*exp != '=' || optr.Top() != '=') //当前元素遇到 =, 或者到栈顶结束符 = 296 { 297 if (isdigit(*exp)) { 298 readNumber(exp, opnd); 299 } 300 else { 301 switch (Precede(optr.Top(), *exp)) 302 { 303 case '<': 304 optr.Push(*exp); exp++; 305 break; 306 case '=': //遇到 ')',将栈顶的'('弹出,并*exp++ 307 optr.Pop(); exp++; break; 308 case '>': 309 op = optr.Pop(); 310 if (op == '!' || op == '~' || (op == '-' && optr.Top() == '(') ) { // 必须加括号??? 311 pnd1 = opnd.Pop(); //若属于一元运算符 312 opnd.Push(Operate(pnd1, op)); //实施一元运算 313 } 314 else { //对其他二元运算符 315 pnd2 = opnd.Pop(), pnd1 = opnd.Pop(); //后出栈的在运算符前:pnd1 op pnd2 316 opnd.Push(Operate(pnd1, op, pnd2)); 317 } 318 break; 319 } 320 } 321 } 322 return opnd.Pop(); //返回最后计算出的数 323 } 324 325 //转换成后缀表达式 326 void CreatePostExp(const char *exp, char *&postexp) 327 { 328 Stack<char> op(EXP_MAX); //定义一个操作数栈 329 op.Push('='); //=是结束标志 330 // cout << "Exp : " << exp << endl; 331 332 // unsigned int j; 333 // unsigned int len = strlen(exp); 334 // //只有一个数的情况 335 // for (unsigned j = 0; j < len && (isdigit(exp[j]) || exp[j] == '.'); j++) { 336 // postexp[j] = exp[j]; 337 // } 338 // if (j == len) { 339 // postexp[j] = ' '; 340 // return; 341 // } 342 343 // for (unsigned int i = 0; i < len; i++) postexp[i] = '0'; 344 345 int k = 0; 346 while (*exp) 347 { 348 if (isdigit(*exp) || *exp == '.') { 349 postexp[k++] = *exp++; 350 } 351 if (isOper(*exp)) { 352 postexp[k++] = ' '; //计算表达式时,' '可以作为一组数字结束的标志 353 switch (Precede(op.Top(), *exp)) { 354 case '<': //栈顶小,当前运算符进操作符栈 355 op.Push(*exp); exp++; break; 356 case '=': //遇到右括号,弹出左括号,*exp++ 357 op.Pop(); exp++; break; 358 case '>': //遇到栈顶运算符优先级高的,则出栈,添加到后缀表达式的后面 359 postexp[k++] = op.Pop(); break; 360 } 361 } 362 postexp[k] = '\0'; //填上结束标志 363 } 364 cout << "后缀表示为: " << postexp << endl; 365 } 366 367 //计算后缀表达试 368 double evaluateRPN(const char *postexp) 369 { 370 Stack<double> ans(EXP_MAX); //操作数栈 371 372 string tmp; //用来转换数字 373 374 // int len = strlen(postexp) 375 // for (int i = 0; i < len; i++) 376 while (*postexp != '\0') //末尾有结束标志 377 { 378 if (isdigit(*postexp) || *postexp == '.') { 379 tmp.push_back(*postexp); postexp++; 380 } 381 else if (*postexp == ' ') { 382 if (!tmp.empty()) { 383 double dtmp; istringstream ss(tmp); ss >> dtmp; //将tmp转换为double型数据 384 ans.Push(dtmp); tmp.clear(); //将数push到栈顶 385 } 386 postexp++; 387 } 388 else if (isOper(*postexp)) { 389 double opnd1 = 0, opnd2 = 0; 390 switch (*postexp) 391 { 392 case '!': //对于一元运算符 393 opnd1 = ans.Pop(); 394 ans.Push(Operate(opnd1, *postexp)); //实施一元运算 395 postexp++; break; 396 case '~': //负数!!! 397 opnd1 = ans.Pop(); 398 ans.Push(Operate(opnd1, *postexp)); //实施一元运算 399 postexp++; break; 400 401 default: //其他二元运算符 402 opnd2 = ans.Pop(), opnd1 = ans.Pop(); 403 ans.Push(Operate(opnd1, *postexp, opnd2)); 404 postexp++; break; 405 } 406 } 407 } 408 return ans.Pop(); 409 410 } 411 412 int main() 413 { 414 //int i; 415 char exp[EXP_MAX] = "(2.2+5)+4*(5-3.1)="; 416 417 char *postexp; 418 postexp = new char[50]; 419 *postexp = '\0'; 420 //char c; 421 double v1; 422 int choice; 423 char pause; 424 425 welcome(); 426 do 427 {//显示主菜单 428 cout << "\t\t\t(支持: +, - , *, /, %, ^, !(阶乘), ~(用\'~\'表示负数).)\n"; 429 cout << "\t\t\t\t1-创建表达式\n"; 430 cout << "\t\t\t\t2-表达式求值\n"; 431 cout << "\t\t\t\t3-求后缀表达式\n"; 432 cout << "\t\t\t\t4-后缀表达式求值\n"; 433 cout << "\t\t\t\t5-显示表达式\n"; 434 cout << "\t\t\t\t6-退出\n"; 435 cout << "\t\t\tEnter choice:"; 436 cin >> choice; 437 switch (choice) 438 { 439 case 1://创建表达式 440 cout << "\n请输入表达式,以=结束: " << endl; 441 cin >> exp; 442 cin.get(pause); 443 system("pause"); 444 cout << endl; 445 break; 446 case 2://表达式求值 447 try { 448 v1 = evaluate(exp); 449 cout << exp; 450 cout << v1 << "\n\n"; 451 } catch (const char *err) { 452 cout << err << endl; 453 } 454 cin.get(pause); 455 system("pause"); 456 cout << endl; 457 break; 458 case 3://求后缀表达式 459 try { 460 CreatePostExp(exp, postexp); 461 cout << endl; 462 } catch (const char *err) { 463 cout << err << endl; 464 } 465 cin.get(pause); 466 system("pause"); 467 cout << endl; 468 break; 469 case 4://后缀表达式求值 470 try { 471 v1 = evaluateRPN(postexp); 472 cout << postexp << " = " << v1 << "\n\n"; 473 } catch (const char *err) { 474 cout << err << endl; 475 } 476 cin.get(pause); 477 system("pause"); 478 cout << endl; 479 break; 480 case 5:// 显示表达式 481 cout << endl; 482 cout << "\n已创建的表达式为:"; 483 cout << exp << endl; 484 if (strlen(postexp)) 485 { 486 cout << "\n后缀表达式为:"; 487 cout << postexp << "\n\n"; 488 } 489 cin.get(pause); 490 system("pause"); 491 cout << endl; 492 break; 493 case 6://退出 494 cout << "结束运行,Bye-Bye!" << endl; 495 break; 496 default:// 497 cout << "Invalid choice\n"; 498 break; 499 } 500 } while (choice != 6); 501 delete postexp; 502 return 0; 503 }//end main