码迷,mamicode.com
首页 > 其他好文 > 详细

表达式计算_控制台版_支持(+,-,*,/,%,^,阶乘)

时间:2016-09-30 07:37:01      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:

  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

测试:

技术分享技术分享技术分享

表达式计算_控制台版_支持(+,-,*,/,%,^,阶乘)

标签:

原文地址:http://www.cnblogs.com/douzujun/p/5922468.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!