计算器C++代码实现—— 中缀表达式的计算
来源:互联网 发布:win10的ps软件 编辑:程序博客网 时间:2024/05/16 00:49
(包含“+ - * / ^ ()”)
这次的程序目的是要将一个中缀表达式转化为后缀表达式并计算,我用两个栈来实现这个功能,一个记录操作符,一个记录操作数,并采取一边转化一边计算的方法最后得出结果。但在这之前,必须先解决以下几个问题。
(1)当遇见“+ - * / ^”操作符时,压人栈之前,什么情况下该从栈里提取操作符计算;而且情况可能很复杂,很可能会导致代码过于冗长。
(2)当有括号时,由于括号的优先级最高,这时该如何处理;
(3)当遇到等号时,很可能符号栈里还有一些(一个或以上)操作符并没有处理,这时该如何判断。
(一)为解决第一个问题,我想了一个办法,就是写一个用来判断符号优先级的函数,我写这个函数是用来解决什么时候该从栈里提取操作符计算的,这里又有几点要说明的;
(1)当遇见"+”“-"则从栈顶是“+ - * / 还是 ^”都应该要提取出来并进行计算。所以这时函数应把这种情况判为真。
(2)当遇见"-”“/"则只有栈顶是“ * / ^”时才提取出来并进行计算且函数应把这种情况判为真。其他判为假。
(3) 当遇见"^”因为“^”优先级高,而且如计算2^2^3,应先算后面,所以这时无论栈顶是“+ - * / 还是 ^”都不应该计算先,而应该先暂时把"^"压人栈,所以这时函数应把这种情况判为假。
(4)当遇见其他操作符时,无需进行优先级判断。或者若栈顶元素是其他操作符时,函数则将此种情况判错。
还有为解决情况太多导致代码过长的问题,我也专门写了一个用来计算并能把并计算结果压人操作数栈的函数。(二)对于第二个问题,只需在遇到“(”时将其压人栈,无需处理,等在当遇到“)”时才将“(”之上的操作符按从上到下依次提取出来并计算,且将“(”弹出栈即可
(三)当遇到“=”时,这时认为表达式结束,则与遇到括号类似,将栈里的符号按从上到下提取出来并计算,这时遇到的另外一个问题就是如何判断符号已经被提取完毕了,我认为这是必须的,因为提取完了还进行提取的话很有可能就会导致程序出错(内存泄露)不过这也很容易解决,只需要在程序刚开始时将"0"压人符号栈来进行接下来的判断即可。
分析完毕后,下面就是我写的程序:
#include<iostream> using namespace std; #include<stack> #include<string> #include<cmath> bool prev(string s1,string s2 ){ //判断符号s1 与 s2 的优先级别的函数 if(s1=="^"||s1=="*"||s1=="/") return true; else if((s1=="+"||s1=="-")&&(s2=="+"||s2=="-")) return true; else return false; } void result(string st,stack<double> &d){ // 计算结果的函数 double x=d.top ();d.pop(); double y=d.top ();d.pop() ; double re; if(st=="+") re=y+x; else if(st=="-") re=y-x; else if(st=="*") re=y*x; else if(st=="/") re=y/x; else if(st=="^") re=pow(y,x); cout<<y<<st<<x<<"="<<re<<endl; d.push(re); } int main(){ string opr,st; //opr 为操作数或操作符,st 用来提取符号栈的符号 stack<double> d; //用来记录计算结果的栈 stack<string> s; //用来记录符号的栈 s.push("0"); //用来判断符号栈里是否还有还有符号,防止出错 double x; //若opr为操作数,则用x表示 while (cin>>opr) { if(opr=="+"||opr=="-"||opr=="*"||opr=="/") { st=s.top(); while(prev(st,opr)) { result(st,d); s.pop(); st=s.top(); } s.push (opr); } else if(opr=="^"||opr=="(") s.push(opr); else if(opr==")") { st=s.top(); while(st!="(") {result(st,d); s.pop(); st=s.top(); } s.pop(); } else if(opr=="=") { st=s.top(); while(st!="0") {result(st,d); s.pop(); st=s.top(); } cout<<d.top()<<endl; d.pop(); } else { x=atof(const_cast<const char *>(opr.c_str()));//类型转换 d.push(x); } } return 0; }
案例:
case1:1 - 0.5 ^ 2 ^ 0 + ( 2 - 1 ) =
2^0=1
0.5^1=0.5
1-0.5=0.5
2-1=1
0.5+1=1.5
1.5
case2:2 + ( 0.5 + ( 2 - 1 ) ^ 2 * 2 ) * 0.5 =
2-1=11^2=1
1*2=2
0.5+2=2.5
2.5*0.5=1.25
2+1.25=3.25
3.25
case3:( 1 + ( 2 / 3 ) ^ 2 ^ 0 ) * 2 =
2/3=0.6666672^0=1
0.666667^1=0.666667
1+0.666667=1.66667
1.66667*2=3.33333
3.33333
通过上面三个案例,经检验,无论是计算次序还是计算结果都没有错,说明我的设计是正确的,但我的程序有两个比较大的缺陷
(1)没有设置判断输入表达式错误的情况,所以必须给出正确的表达式才能进行正确的计算,如给出错误的表达式,本应该给出报错的,但还是会进 行计算,可惜因为输入情况错误的情况过多,判断起来过于复杂,所以我就没有进行判断。
(2)输入的时候太麻烦,因为每次输入一个操作符或操作数时,都要空格,这是因为string的限制,我暂时也没有想到好的办法解决这个问题
不过,我认为我的程序也有一个很大的优点,那就是易于推广,如要进行对数或三角数的计算,只需加入"log" "sin"等符号并判断优先级 别并用相应的计算方法即可,并不会导致程序过于复杂。
- 计算器C++代码实现—— 中缀表达式的计算
- C语言实现括号匹配,中缀表达式转后缀表达式并计算具体代码实现
- 数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代码实现)(1)
- CodeDom计算器——动态计算数学表达式的实现
- 自己实现的一个中缀表达式计算
- 中缀表达式转后缀表达式实现实例——Android计算器
- 计算器实现---中缀表达式转后缀表达式
- C语言实现括号匹配,中缀表达式转后缀表达式并计算的算法
- C语言简易计算器(中缀表达式转后缀表达式,通过堆栈实现)
- 计算中缀表达式的值
- 计算中缀表达式的值
- #C++实现先中缀转后缀的算术表达式计算
- 中缀表达式转后缀表达式 (中缀表达式的计算)
- 栈的应用--中缀表达式转换为后缀表达式&逆波兰计算器的实现
- 中缀表达式计算器
- 【JS】中缀表达式计算器
- 中缀表达式计算器
- 中缀表达式计算器
- 如何得到plsql中执行时报错的SQL的位置行号
- 实时开发框架Meteor 实际应用系列<一>---文件的上传和下载
- ubuntu 13.10 64 安装subclipse
- 装ubuntu遇到的一些问题 && solution
- 用python获取贴吧中留下的邮箱
- 计算器C++代码实现—— 中缀表达式的计算
- GOOSE入门
- 新的开始
- 【JAVA学习】java中==、equals()、hashCode()都和对象的比较有关,在java中这三者各有什么用处呢,即java中为什么需要设计这三种对象的比较方法呢?
- JSTL 核心标签库 使用
- Effective Java 第5条 避免创建不必要的对象
- CDH 4.6 Apache Hadoop的下一代mapreduce,yarn
- apt-get update message---------what do Ign Error Hit Get 
- POJ 2531 Network Saboteur