表达式计算 控制台

  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

 

posted @ 2016-09-30 00:45  douzujun  阅读(349)  评论(0)    收藏  举报