C# · 12月 20, 2021

C++实现计算器

后缀表达式,又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行,所以不需要算符优先级,这对我们编写计算器来说很好实现

比如给定一个中缀表达式:

1 + 3 * 5 – ( 7 / 9 )

其后缀表达式应为:

1 3 5 * + 7 9 / –

首先要理解如何进行转换,先按照运算优先级对其加上括号

1 + 3 * 5 – ( 7 / 9 ) = ( (1 + (3 * 5 ) ) – ( 7 / 9 ) )

然后依次把优先级高的括号转为后缀

((1+(3*5)) – (7/9))

–> ((1 + (35*)) – (79/))

–> ((1 (35*)+) – 79/)

–> (135*+)(79/)-

–> 135*+79/-

整体步骤

中缀表达式转后缀表达式

计算后缀表达式

第一步:

中缀表达式转后缀表达式

自左向右读入中缀表达式

数字时,加入后缀表达式;

运算符:

-若为 ‘(’,入栈

-若为 ‘)’,则依次把栈中的的运算符加入后缀表达式中,直到出现’(’,从栈中删除’(’

-若为除括号外的其他运算符, 当其优先级高于除’(‘以外的栈顶运算符时,直接入栈。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号为止,然后将其自身压入栈中(先出后入)。

当扫描的中缀表达式结束时,栈中的的所有运算符出栈;

具体图示:

第二步计算后缀表达式

建立一个栈S 。从左到右读表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作数运算,再将运算的结果代替原栈顶的n项,压入栈S中 。如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。

简言之:从左到右读表达式遇到操作数压入栈中遇到操作符取并弹出栈顶n个元素,(n取决于操作符是n元操作符),计算结果压入栈中后缀表达式读完,当前栈顶元素及为结果代码如下#include #include#include #includeusing namespace std;double CalSuffix(string suffix){double result;stack number;int i = 0,j;int n=0;//判断是否为数字string current;while(suffix[i]!=’#’){isNum=0;if(suffix[i]==’|’){for(j=i+1;; j++){if(suffix[j]==’|’)break;if(suffix[j]==’#’)break;}//获取|A|之间元素for(int k=i+1; k num;number.push(num);isNum = 1;break;}}if(isNum!=1){double n2 = number.top();number.pop();double n1 = number.top();number.pop();if(current==”+”){number.push(n1+n2);}else if(current==”-“){number.push(n1-n2);}else if(current==”*”){number.push(n1*n2);}else if(current==”/”){number.push(n1/n2);}}current=””;//清空当前字符串;}i++;}if(number.size()!=1)cout<<"输入有误"<=48 && Infix[i]=48 && Infix[i]=48 && Infix[i]<=57) //小数部分{Suffix[j++] =Infix[i];i+=1;}}}else if(Infix[i]=='(')//如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低。{operate.push(Infix[i++]);}else if(Infix[i]==')')//如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串。{if(operate.empty())//没有左括号cout<<"表达式错误"<<endl;else{currentOp = operate.top();while(currentOp!='('){cout<<currentOp<<endl;Suffix[j++]='|';Suffix[j++]=currentOp;operate.pop();if(operate.empty()){cout<<"表达式错误"<=48 && Infix[i]=48 && Infix[i]=48 && Infix[i]<=57) //小数部分{Suffix[j++] =Infix[i];i+=1;}}}continue;}}//如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶if(operate.empty()){operate.push(Infix[i++]);}else{char top = operate.top();//栈顶if(Priority(top)=Priority(Infix[i])){Suffix[j++]='|';Suffix[j++]=top;operate.pop();if(!operate.empty()){top = operate.top();}elsebreak;}operate.push(Infix[i++]);//放入栈顶并指向下一个}}}else{cout<<"符号错误"<<endl;i+=1;}}//顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串。while(!operate.empty()){char to = operate.top();Suffix[j++]='|';Suffix[j++]=to;operate.pop();}Suffix[j] = '#';//结束符cout<<Suffixa;istringstream iss(a);double num;iss >> num;cout<<num;cout<<"后缀为:"<<Infix2Suffix(a)<<endl;cout<<CalSuffix(Infix2Suffix(a));return 0;}