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