使用逆波兰式(后缀表达式)实现多功能计算器

由于这是之前的小作业了,之前贴出来没注意,后来发现格式太乱了根本看不了,所以今天再贴出来一下,这次的计算器比我之前写的要复杂很多,主要是通过逆波兰式实现的,没有界面,计算器是我之前的一个软肋啊,编了好多次都没有写出来。
这次这个,我试着调了很多次bug,以及很多种情况,尽量完善了,但是如果还有没考虑周全的,希望大家提出来,亲测代码可用。当然,为了方便起见,我把代码都整合到一个cpp文件的,主要也是懒。。。
一.以下是本计算器实现的功能。

支持+ - * / 四则运算
支持 小数 +(正号) -(负号) %(百分号) !(阶乘)
支持 sin cos tan arctan arcsin arctan fabs exp log2 log10 ln sqrt等函数
支持输出变量 变量赋值 变量计算 pi/PI E/e ^(次方)
clearAll(清除所有) clear变量(清除指定变量) showALL(显示所有变量) fprecise 数值(按照指定精度输出)EXIT(退出) Ang(输入按照角度进行计算) RAD(输入按照弧度进行计算)等指令
输入的函数不区分大小写,变量 区分大小写,指令限于以上格式

二.下面是程序的每一步的实现步骤

2.1 主要步骤,代码顺序也是如此

2.1.1字符串预处理,提取变量,检测指令
实现内容:
检测输入表达式是否为指令,若是,则执行该指令
检测符合指令格式的错误指令
检测表达式是否为赋值语句
若表达式为赋值语句,检测变量名是否符合要求
检测表达式中运算的变量,并替换掉相应的变量
替换掉表达式中的pi(圆周率)和e(自然对数)
将处理后的表达式全部转化小写

实现方法
1.使用STL中map结构,建立一个map映射存储变量以及相应的值
2.使用相应的标记存储用户输入的rad/ang/fprecise等指令,从而改变程序的运行
3.showALL/clear/clearAll等指令以及输出变量值指令即遍历和删改map映射
4.检测“=”前面的字符串,若符合变量命名要求,则将其暂时存储,且将“=”后的表达式截取下来。若不符合,结束该次运算。
5.将映射中存储的变量与“=”后的表达式相比对,替换掉“=”后表达式中的变量以及pi/e值

2.1.2字符串错误检测(形式上的错误)
实现内容

1.检测数学函数名是否错误
2.检测数学函数后是否括弧匹配(成对),以及函数后是否有括弧
3.检测字符是否在正常范围内
4.检测括弧是否成对存在,以及”(“前后的字符是否正确,”)”前后的括弧是否正确
5.分别检测+,-,*,/号前后的字符是否正确
6.检测!,%符号前后的字符是否正确
7.检测 . 前后的字符是否正确,以及表达式第一个字符是否正确

实现方法
使用穷举法,根据资料以及多次的测试,总结出以下的可能错误:
1.函数名错误,函数名后面没有括弧或者括弧不匹配
2.表达式字符未在正确范围内
3.括弧未成对存在,’(’ 之前 + - * / ( ^ 函数 有效, ‘(’ 之后 + - ( 0~9 ! %函数 有效,(log10(),log2()除外)’)’ 之前 0~9 ) % !有效, ‘)’ 之后 + - * / ^ ) 有效。
4.首字符不能为* / % ^ !等 ,结尾不能出现 + - * / . 函数
5.+ - 符号之前 . 无效, 之后 * / ) . % ! 无效。
* / 符号之前 + - * / . ( 无效, 之后 * / ) . % ! 无效。
6.!前0~9 )有效,!后不能有0~9 ( 字母
%前0~9 )有效,%后不能有0~9 ( 字母
7. . 前后必须为数字,且两个 . 之间不能为纯数字
根据以上可能错误,一个个进行排查,当所有条件都满足时,便是一个合格的表达式,方可进行下一步运算。由于考虑到+(正号)-(负号)的存在,+ -处理和* /有所不同

2.1.3将字符串转化为逆波兰式
实现内容
将复杂的表达式通过逆波兰式算法转化为逆波兰式
识别表达式中的正负号,并处理掉

如何实现
1.为识别多个连续的正负号,如+++3 —-3等,我们选择从表达式最后向前遍历,如果一个+ 或-前面的字符是+ - * / ( ^ ,则该+ - 为正负号,正号直接删除,负号用~代替
2.隐含在表达式最后以及符号栈底加入“#”作为结束标志
3.转换步骤:# ( +- */ ~ ! % ^ )优先级依次增加。
但是在计算时遇到正负以及函数等左单目运算,压入符号栈。遇到!%等右单目运算将其压入逆波兰式栈中。
4.其余的与普通逆波兰式转换相同,不再赘述

2.1.4计算逆波兰式
实现内容
1.将转换成的逆波兰式计算出来
2.检测逻辑上的错误

如何实现
1.经过总结,形式上的语法错误,有如下:
负数或小数阶乘 除数为零
负数根号 反正弦函数定义域在-1到1之外
反余弦函数定义域在-1到1之外 对数函数计算零或负数
2.计算逆波兰式有如下的步骤:
按生成的逆波兰式从左向右遍历,如果为数据,则将其压入中间栈
如果为单目运算,则弹出一个中间栈数据进行运算
如果为双目运算,则弹出两个中间栈数据运算
注意被除数与除数的顺序,将计算的结果继续压入中间栈

运行案例
这里插几张运行的图片吧:
使用逆波兰式(后缀表达式)实现多功能计算器_第1张图片

使用逆波兰式(后缀表达式)实现多功能计算器_第2张图片

使用逆波兰式(后缀表达式)实现多功能计算器_第3张图片

实现代码

多功能计算器实现代码以及详解

你可能感兴趣的:(编写历程)