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

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

   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/-

整体步骤

  • 中缀表达式转后缀表达式
  • 计算后缀表达式

第一步:

中缀表达式转后缀表达式

自左向右读入中缀表达式

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

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

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

具体图示:

第二步

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

  1. 从左到右读表达式
  2. 遇到操作数压入栈中
  3. 遇到操作符取并弹出栈顶n个元素,(n取决于操作符是n元操作符),计算结果压入栈中
  4. 后缀表达式读完,当前栈顶元素及为结果

代码如下

#include <iostream>
#include<stack>#include <sstream>
#include<stdlib.h>
using namespace std;double CalSuffix(string suffix)
{double result;stack<double> 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<j; k++){current+=suffix[k];}//判断是否为数值for(int k=0; k<current.size(); k++){if(current[k]>=48 && current[k]<=57)//数字{//strinf转doubleistringstream iss(current);double num;iss >> 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<<"输入有误"<<endl;elsereturn number.top();}int Priority(char operate)//栈中优先级
{switch(operate){case '+':case '-':return 2;case '*':case '/':return 3;case '(':case ')':return 1;default:return 0;}
}string Infix2Suffix(string Infix)
{stack<char> operate;string Suffix = "                               ";//初始化后缀表达式char currentOp;int negative;int i = 0,j = 0;//i为中缀当前指向 j为后缀当前指向while(Infix[i]!='\0'){if(i+1!='\0')negative = 0;if(Infix[i]>=48 && Infix[i]<=57) //判断数字{Suffix[j++] = '|';//j是后缀表达索引Suffix[j++] =Infix[i];//存储当前数字并指向下一个while(Infix[++i]>=48 && Infix[i]<=57) //整数部分{Suffix[j++] =Infix[i];}if(Infix[i]=='.') //是小数{Suffix[j++]='.';i+=1;//中缀索引 往后移while(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<<"表达式错误"<<endl;break;}currentOp = operate.top();}operate.pop();//删除栈中(i++;}}else if(Infix[i]=='+'||Infix[i]=='-'||Infix[i]=='/'||Infix[i]=='*'){//判断负数if(Infix[i]=='-'){if(i==0)//第一个为‘-’时为负号negative = 1;else if(Infix[i-1]=='+'||Infix[i-1]=='-'||Infix[i-1]=='/'||Infix[i-1]=='*')//如果前面有操作符则为负号negative = 1;if(negative==1){Suffix[j++] = '|';//负号Suffix[j++] = '-';i+=1;if(Infix[i]>=48 && Infix[i]<=57) //判断数字{Suffix[j++] =Infix[i];while(Infix[++i]>=48 && Infix[i]<=57) //整数部分{Suffix[j++] =Infix[i];}if(Infix[i]=='.') //是小数{Suffix[j++]='.';i+=1;while(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])) //放入的符号优先级低于栈顶{operate.push(Infix[i++]);//放入栈顶并指向下一个}else//如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串。{while(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<<Suffix<<endl;return Suffix;
}int main()
{string a;cin>>a;istringstream iss(a);double num;iss >> num;cout<<num;cout<<"后缀为:"<<Infix2Suffix(a)<<endl;cout<<CalSuffix(Infix2Suffix(a));return 0;
}

转载于:https://www.cnblogs.com/xiatom/p/10784867.html

C++利用栈实现计算器相关推荐

  1. 手把手带你利用栈来实现一个简易版本的计算器

    手把手带你利用栈来实现一个简易版本的计算器 什么是栈 栈的实现 通过数组实现 通过队列实现 实现思路 栈的经典应用场景 浏览器前进后退 括号配对 leetcode 20 题 表达式求值 leetcod ...

  2. 数据结构与算法(3-1)栈(顺序栈、两栈共享空间、链栈、栈的计算器)

    目录 一.顺序栈 存储结构 总代码 二.两栈共享空间 存储结构: 总代码: 三.链栈 存储结构: 总代码: 一.顺序栈 存储结构: 栈特点:先进后出,后进先出.(特殊的线性表) 入栈时在栈顶添加元素, ...

  3. 小妹使用栈实现计算器(上)

    hello,大家好,今天给大家讲的是利用栈实现一个计算器,思路很简单,大家仔细思考. 好了,废话不多说,马上开始. 小妹:小哥哥,我前几天写了一个计算器,你来帮我看看怎么样吧. 我:恩?计算器,拿来吧 ...

  4. 小妹使用栈实现计算器(下)

    接上篇:小妹使用栈实现计算器(上) 我:好饱,怎么样,写出来了么?看你那愁眉哭脸,指定没写出来. 小妹:你很开心? 我:哈哈哈,也不是,就是吃饱了,舒坦. 小妹:找打呢你! 我:我来给你讲,别急别急. ...

  5. 利用“栈”解决“出轨”问题

    本图文利用"栈"的知识解决了"出轨"问题!

  6. 数据结构之迷宫问题求解(一)利用栈与递归求解出口

    本文适合于对迷宫问题已有初步研究,或阅读代码能力较强的人. 因此,如果你对迷宫问题一无所知,请参考其他更详细的资料. 迷宫问题,是一个对栈(Stack)典型应用的例子之一. 假如,有如下10X10的迷 ...

  7. C语言中用栈实现进制转换,利用栈实现进制转换问题

    进制转换问题 建立顺序栈或链栈,编写程序实现十进制数到二进制数的转换. 输入 输入只有一行,就是十进制整数. 输出 转换后的二进制数. 样例输入 10 样例输出 1010 十进制怎么转为二进制?十进制 ...

  8. 利用栈进行程序的括号匹配

    利用栈进行程序的括号匹配 程序代码: /** fanchen.cpp : 定义控制台应用程序的入口点.**/#include "stdafx.h" #include <ios ...

  9. 数据结构:利用栈,将递归转换为非递归的方法

    利用栈将递归转换为非递归 对于一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化,可直接写出相应的非递归算法. 步骤 第一次调用的参数push进堆栈,原有递归代码外层加一个while循环,判断 ...

最新文章

  1. 贴牌是赢在当下,创牌才会更有未来
  2. 【Windows程序设计】Unicode简介
  3. ik分词器实现原理_SpringBoot整合Elasticsearch实现商品搜索
  4. 收到几本书,顺便热热身
  5. Spring Cloud——Consul——架构体系
  6. 从链接中获取文件名及扩展名
  7. Digital Text Animations for Mac - 未来感活力全屏标题动画fcpx插件
  8. metadata.js
  9. Vue Router history模式的配置方法及其原理
  10. 2017.8.15 阿狸的打字机 失败总结
  11. 庆祝西安.NET俱乐部成立,请申请加入的朋友在这里报到
  12. mosquitto查看订阅记录_Mosquitto\Client
  13. 配置ssm 时, web.xml 文件无 # 自动代码提示
  14. webpack2中postcss-loader报错noconfigfound
  15. VS C++ string转int int转string
  16. 为胎儿诵地藏经的好处(合集)怀孕的一定要看哦!
  17. mysql连接被拒绝 密码也对_MYSQL密码正确,却依然显示拒绝连接
  18. Gromacs源码收获(四)
  19. 【Unity3D入门教程】使用C#脚本控制游戏对象
  20. java毕业设计会议室预约管理系统(附源码、数据库)

热门文章

  1. S2SH 第一次整合的经历
  2. 携号转网可能只会叫好不叫座
  3. NeatUpload:支持大文件上传 进度条
  4. 关于CSS兼容IE与Firefox要点分析
  5. 服务器主板点不亮排查
  6. SQL Server外连接、内连接、交叉连接
  7. shell 日志统计常用脚本
  8. Android控件——ListView之Adapter提供数据(其二)
  9. NAT应用于HSRP环境
  10. Hibernate中的fetch