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

  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

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

自动配置数据库_控制台版 还原数据库

错误提示: 配置截图: 原因:数据库名"5"并不是名称为"Sdzn"的数据库备份文件的实际逻辑名称 查看名称为"Sdzn"的数据库备份文件的实际逻辑名称: 由以上截图可以看出应把"5"改成"SdznSmartCloudEdu_Empty" [ 注: 在SQL Server中一共有3个名称:数据库名称.逻辑文件名.物理文件名.其中SdznSmartCloudEdu_Empty与SdznSmartClo

鸟哥的Linux私房菜_基础版_学习笔记9:第十三章 学习 Shell Scripts

13.1 什么是 Shell scripts 13.1.1 干嘛学习 shell scripts 13.1.2 第一支 script 的撰写与运行 在 shell script 的撰写中还需要用到底下的注意事项: 命令的运行是从上而下.从左而右的分析与运行: 命令的下达就如同第五章内提到的: 命令.选项与参数间的多个空白都会被忽略掉: 空白行也将被忽略掉,并且 [tab] 按键所推开的空白同样视为空白键: 如果读取到一个 Enter 符号 (CR) ,就尝试开始运行该行 (或该串) 命令: 至於

鸟哥的Linux私房菜_基础版_学习笔记7:第十一章 认识与学习 BASH

11.1 认识 BASH 这个 Shell 图 1.1.1.硬件.核心与用户的相关性图示 11.1.4 Bash shell 的功能 既然 /bin/bash 是 Linux 默认的 shell ,bash 是 GNU 计划中重要的工具软件之一,目前也是 Linux distributions 的标准 shell . bash 主要兼容于 sh ,并且依据一些使用者需求,而加强的 shell 版本.不论你使用的是那个 distribution ,你都难逃需要学习 bash 的宿命啦!那么这个 s

鸟哥的Linux私房菜_基础版_学习笔记8:第十二章 正规表示法与文件格式化处理

11.2 基础正规表示法 11.2.1 语系对正规表示法的影响 由於不同语系的编码数据并不相同,所以就会造成数据撷取结果的差异了. 举例来说,在英文大小写的编码顺序中,zh_TW.big5 及 C 这两种语系的输出结果分别如下: LANG=C     时:0 1 2 3 4 ... A B C D ... Z a b c d ...z LANG=zh_TW 时:0 1 2 3 4 ... a A b B c C d D ... z Z 特殊符号 代表意义 [:alnum:] 代表英文大小写字节及

鸟哥的Linux私房菜_基础版_学习笔记4:第八章 Linux磁盘与文件系统管理

8.1认识 EXT2 文件系统 8.1.1硬盘组成与分割的复习 各种接口的磁盘在Linux中的文件名分别为: /dev/sd[a-p][1-15]:为SCSI, SATA, U盘, Flash闪盘等接口的磁盘文件名: /dev/hd[a-d][1-63]:为 IDE 接口的磁盘文件名: 8.1.2文件系统特性 文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data block 区块中. 另外,还有一个超级区块 (superblock)

鸟哥的Linux私房菜_基础版_学习笔记3:第七章 Linux文件与目录管理

第七章 Linux文件与目录管理 7.1目录与路径: 7.1.1相对路径与绝对路径: 绝对路径:路径的写法『一定由根目录 / 写起』,例如: /usr/share/doc 这个目录. 相对路径:路径的写法『不是由 / 写起』,例如由 /usr/share/doc 要到 /usr/share/man 底下时,可以写成:『cd ../man』这就是相对路径的写法啦!相对路径意指『相对於目前工作目录的路径!』 7.1.2目录的相关操作: . 代表此层目录 .. 代表上一层目录 - 代表前一个工作目录

鸟哥的Linux私房菜_基础版_学习笔记5:第九章 文件与文件系统的压缩与打包

9.2 Linux 系统常见的压缩命令: *.Z compress 程序压缩的文件: *.gz gzip 程序压缩的文件: *.bz2 bzip2 程序压缩的文件: *.tar tar 程序打包的数据,并没有压缩过: *.tar.gz tar 程序打包的文件,其中并且经过 gzip 的压缩 *.tar.bz2 tar 程序打包的文件,其中并且经过 bzip2 的压缩 9.2.1 compress  [[email protected] ~]# apt-get install ncompress

鸟哥的Linux私房菜_基础版_学习笔记6:第十章 vim 程序编辑器

10.1 vi 的使用 基本上 vi 共分为三种模式,分别是『一般模式』.『编辑模式』与『指令列命令模式』. 这三种模式的作用分别是: 图 2.1.vi 三种模式的相互关系 10.2.1简易执行范例 1.使用 vi 进入一般模式: [[email protected] ~]# vi test.txt 上半部显示的是档案的实际内容,最底下一行则是状态显示列(如下图的[New File]信息), 或者是命令下达列喔! 图 2.1.1.用 vi 开启一个新档案 如果你开启的档案是旧档(已经存在的档案)

linux入门_韩顺平_复习版_简介

关键词 linux是什么 linux历史 linux和windoows对比 linux是什么 linux是linus主开发的一款操作系统,免费.开源.高效.安全,企业级的项目大部分部署在linux/unix上. linux历史和类型 70s,贝尔实验室的b.c语言之父Ken tompson和Dennis richres用c编写了unix操作系统 80s,IBM等企业在unix基础上开发了各自的操作系统,使用价格高昂,不对大众开发. 开源运动之父Richard Stallman强调自由时代,用户应