




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、,.表达式计算 -c+1,这是使用 c+编写的一个表达式转后缀式再求值的一个类2,由于本人只是学生一个, 这些都是为了验证学习上的东西,写得比较粗糙, 只供初学者参考3,本类可以计算小数,负数。只能识别 + - * / % ( 这是一个乘方运算符,用法如 :216计算 2的16次方,%这是一个求余运算符, 使用规则和 c+编译器类似 ) ,只能包含 () 这一种括号,并且在操作数和括号之间的运算符不能省略,每个运算符要明确给出4,本类负数处理的方法是采用 : 符号来替换,可以在表达式中输入 (-) 负号,但在字符检测函数来区分负号时,如果检测出来是负号就会自动转换为(:) 这个符号。这主要是为
2、了在以后计算时可以不用每次来区分是不是负号, 而只区分一次即可。 也可以直接在表达式中用 : 这个符号来表示负号,识别函数可以直接识别而不需要区分和替换。要注意的是, (-) 这种负号一定要使用表达式检查函数才能识别,如果不想使用检查函数,就只能用 : 来代替。5,本类的表达式检查函数会按照一定的规则来检测表达式输入是否合要求,如果有不合要求的字符或字符位置不合要求都会报错, 并会指出是那一个字符, 而且当函数检测到一个错误时不会立即停下, 而会继续检测, 只到表达式结束。 并输出表达式中的那些字符不合要求。6,单个 0是不能出现在表达式中, 但0.0 可以,如果表达式中需要出 0可以用 0.
3、0 代替,但如:30/0.0 这样的计算会在计算时给出错误提示。7,表达式中可以出现 -(-(-13+5)+5) 这样的深层负号计算,计算结果和 vc+编译器结果一样8,本类在 vc6.0,w7系统下编译通过并运算。9,本类中没有主动清空数据成员的方法,所以有使用时,要将类的对象定义在计算循环或;.,.函数内,这样每一次计算都会对对象进行创建和析构,不然会出现异常, 当然你可以增加一个清空数据成员的方法。/ 以下是 expevaluate.h 类的头文件#ifndef exp_h#define exp_h#include /字符串类头文件#include /stl 栈头文件#include /
4、stl 队列头文件#include /stl 向量头文件#include /stl 链表头文件using namespace std;class expevaluatepublic:expevaluate();/用于初始化错误列表void expinto(string &exp);/输入一个表达式int expdetector();/字符串规则检测函数int expidentification(char exp);/ 数字运算符识别函数int exppriority(char ope);/ 返回运算符的优先级void expsuffix();/ 将表达式转为后缀式double expcompu
5、te();/计算后缀表达式,并返回结果void errorbacktrack();/根据错误号返回相应错误private:stringexps;/表达式字符串stackoper;/运算符栈stackoperand;/操作数栈queuepostfix;/后缀队列vector error;/错误列表listindex;/ 错误索引表intgrade;/ 错误标号stringerrorout;/错误输出缓冲区double opreadop();/读取操作数,并返回转换后的结果double oporder(double op,double x);/ 求 op 数的 x 次方;#endif/ 以下是 .
6、cpp 实现文件;.,.#include expevaluate.h#include resource.h#include / 字符转换数字头文件#include #include expevaluate:expevaluate()/初始错误列表error.resize(15);/ 为列表初始为15 个元素grade=0;/ 初始标号为0,表示没有错误error.at(0)=操作数错误:操作数前不能是)右括号!;error.at(1)=操作数错误:0 不可以出现在操作的开始,也不能作为一个单独的操作数!;error.at(2)=操作数错误:小数点不能在一个操作数中重复出现!;error.at(
7、3)=运算符错误:运算符前面必须是操作数或)右括号,并且运算符不能重叠!;error.at(4)=括号错误:左括号前面必须是运算符或左括号或负号!;error.at(5)=括号错误:右括号前面必须是操作数或右括号!;error.at(6)=括号错误:括号输入不匹配 !;error.at(7)=分隔符错误: #号分隔符只能出现在表达式的边界位置!;error.at(8)=表达式错误:表达式的结尾必须是操作数或右括号!;error.at(9)=负号错误:负号前面必须是运算符或左括号呀分隔符!;error.at(10)=字符错误:表达式中除数字,运算符,:负号, () 括号之外不能出现其它符号 !;
8、error.at(11)=计算错误:除数不能为 0,也不能小于0.0001( 个人限制 )!;error.at(12)=计算错误:求余运算中 ,除数不能为 0或小于 0!;error.at(13)=计算错误:次方运算中 ,次方数不能小于 0!;error.at(14)=计算错误:计算结果出现错误 !;void expevaluate:errorbacktrack()list:iterator pexp;/ 使用迭代器来遍历链表char m18;/ 字符缓冲区if(grade=0)/如果错误标号为0 表示没有错误,就直接返回return;else if(grade=1)/ 如果为 1 表示错误由
9、检测函数发现for(pexp=index.begin();pexp!=index.end();)/ 通过 sprintf 函数将错误的字符位置整数,格式化到字符缓冲区数组m 中sprintf(m, 错误字符位置:%2d,*pexp);errorout+=m;/ 将格式化的字符连接到错误输出缓冲区中pexp+;errorout+=error.at(*pexp);/ 将相对应的错误提示连接至缓冲区中errorout+=rn;pexp+;.,.couterroroutendl;/ 输出错误else if(grade=2)/ 如果错误标号为 2,表示是在计算时发现for(pexp=index.begi
10、n();pexp!=index.end();)/ 将相应的错误连接到错误缓冲区中 errorout+=error.at(*pexp); errorout+=rn;pexp+;couterrorout=48&iexp=57)return 1;/表示识别到的是数字和小数点switch(iexp)case 94:case 37:case 43:case 45:case 42:case 47:return 2;/表示识别到 +-*/ 运算符case 40:case 41:return 3;/表示识别到括号case 35:return 4;/如果是 #号 ,这只是一个分隔符,没有其它含意case 58:
11、return -1;/用这个符号来替换负号,表示识别到一个负号return 0;/表示识别到其它运算符int expevaluate:exppriority(char ope)/返回运算符的优先级switch(ope)case :;.,.return 4;/赋于次方运算符最高优先级case %:case *:case /:return 3;/ 赋于 * , /,%侁先级case +:case -:return 2;case (:return 1;return 0;/ 如果不是运算符就返回0void expevaluate:expinto(string &exp)/ 输入一个表达式if(exp.
12、empty()return;exps=exp;/ 将表达式输入到类中exps.insert(0,#);/在表达式的边界加入一个分隔符,以简化规则检测exps+=#;return;int expevaluate:expdetector()/ 字符串规则检测函数,采用向前检测int i=1,frequency=0;/frequency 为小数点标志,每一个操作数能出现一位小数点int sign=1;/ 如果出现错误就将标志位改为0,否则就不改变char interspace;while(iexps.size()/ 一直读到最后一个字符interspace=exps.at(i);switch(exp
13、identification(interspace)/ 判断每一个字符是否合规则case 1: /如果是操作数if(exps.at(i-1)=)index.push_back(i);/ 记录错误位置index.push_back(0);/记录错误信息号grade=1;/将标志位至1,说明是检测函数检测的错误sign=0;/如果有错误就将返回标志至0break;.,.else if(interspace=0)/ 对 0 进行特别检测if(expidentification(exps.at(i-1)!=1) / 如果 0 出现在一个操作数的开始,那这个数必须为小数 if(exps.at(i+1)!
14、=.)/ 如果如果不是小数就算是非法数index.push_back(i);index.push_back(1);grade=1;sign=0;break;else if(interspace=.)/ 如果操作数中出现小数点,就必须将其标志,心防止出现多个小数点if(frequency=1)index.push_back(i);/记录错误位置index.push_back(2);/ 记录错误信息号grade=1;/ 将标志位至1,说明是检测函数检测的错误sign=0;/ 如果有错误就将返回标志至0break;elsefrequency=1;/ 如果操作数中出现小数点就将标志置1break;ca
15、se 2:/需要检测运算符是否合规则,并检测负号frequency=0;/ 如果出现运算符就说明是另一个操作数,这时需要将小数点标志置0if(interspace=-)/ 如果是 -号就需要判断是运算还是负号if(expidentification(exps.at(i-1)=2|exps.at(i-1)=(|exps.at(i-1)=#)/如果 -号前面是运算符或(括号或#号并且后面要是数字,这样就说明-号是负号exps.replace(i,1,:);/如果是负号就将它替换为:号break;if(expidentification(exps.at(i-1)!=1 & exps.at(i-1)!
16、=);.,./ 如果运算符的前面不是操作数或不是)括号,index.push_back(i);index.push_back(3);grade=1;sign=0;break;break;case 3:/需要检测括号是否合规则if(interspace=()if(expidentification(exps.at(i-1)!=2 & exps.at(i-1)!=: & exps.at(i-1)!=( & exps.at(i-1)!=#)/增加 & exps.at(i-1)!=: 这个条件就可以处理-(-(12+3)+3) 这样的多层嵌套负号计算功能index.push_back(i);index
17、.push_back(4);grade=1;sign=0;oper.push(interspace);/是左括号就压栈elseif(expidentification(exps.at(i-1)!=1 & exps.at(i-1)!=)/如果右括号前面必须是操作数或右括号index.push_back(i);index.push_back(5);grade=1;sign=0;if(oper.empty()|oper.top()!=()index.push_back(i);index.push_back(6);grade=1;sign=0;elseoper.pop();/ 如果右括号匹配就将括号弹
18、出break;.,.case 4:/如果读到分隔符,这个在这里只能出现在边界if(i!=0 & i!=exps.size()-1)index.push_back(i);index.push_back(7);grade=1;sign=0;elseif(expidentification(exps.at(i-1)!=1 & exps.at(i-1)!=)/如果结尾处不是操作数或右括号就出错index.push_back(i);index.push_back(8);grade=1;sign=0;break;case -1: / 如果读到负号 if(expidentification(exps.at(
19、i-1)!=2 & exps.at(i-1)!=( & exps.at(i-1)!=#)index.push_back(i);index.push_back(9);grade=1;sign=0;break;case 0:/如果读到非法字符就输出相应提示index.push_back(i);index.push_back(10);grade=1;sign=0;break;i+;if(!oper.empty()/如果括号匹配栈不为空就输出错误提示index.push_back(i-1);/记录错误字符位置index.push_back(6);/ 记录相对应的错误信息号grade=1;/ 将标志修改
20、为1,不示是检测函数发现的错误sign=0;/ 将返回值标志至0,表示有错误;.,.while(!oper.empty()/如果不为空就将它清空oper.pop();return sign;/sign 为 1 表示表达式无错误,为0 表示有错误/当返回值为0,就调用错误输出函数来输出错误double expevaluate:oporder(double op,double x)int n=(int)x,i;/ 参数 x 之所以定为浮点型是为了简化操作double sum=1;if(n=0)/0 的任何次方都为1return 1;for(i=0;in;i+)sum*=op;/获取 op 的 x
21、次方return sum;void expevaluate:expsuffix()/ 将表达式转为后缀式int i=0;char interspace,m;while(iexps.size()interspace=exps.at(i);switch(expidentification(interspace)case 1:/ 如果读到的是操作数就直接入后缀postfix.push(interspace);break;case -1:/ 如果是负号就判断是否是-(12+3) 之类的表达式postfix.push(interspace);/ 先将负号直接入后缀if(exps.at(i+1)=()/判
22、断负号的下一位是不是左括号/ 如果下一位是括号,说明就是 -(12+3) 这种情况 ,遇到这种就将负号改为 -0-postfix.push(0);/ 加上 0 就将负号变为 -0 操作数了;.,.postfix.push(#);/ 将负号变为 -0 操作数后要记得加上分隔符oper.push(-);/ 并要加上一个减号,(这样可以达到负负得正,正负得负的目的)/ 这里的思想是将-(12+3) 替换为 -0-(12+3), 这样就可以处理-(-(-() 这样的负号break;case 2:/如果读到的是运算符就压入运算符栈postfix.push(#);/ 连续操作数之间用#号隔开if(oper.empty()oper.push(interspace);/如果栈为空就直接压入栈else/ 如果栈不空就要比较运
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2030中国AM和和FM收音机行业发展趋势分析与未来投资战略咨询研究报告
- 冷库主管工作总结
- 2025至2030中国心耳封堵器行业产业运行态势及投资规划深度研究报告
- 铁路隧道消防培训
- 2025年智能可穿戴设备个性化健康服务技术创新报告
- 欺诈性债务抵消:虚构合同解除与补偿协议
- 蒙氏混龄班老师工作总结
- 高铁站空调采购、安装及旅客舒适度提升合同
- 离婚协议书中财产分割、子女抚养及共同财产清算协议
- 离婚协议违约金及财产分配纠纷解决合同
- 危重病人抢救制度课件
- 家具制造业2025年原材料价格波动对行业市场发展趋势影响报告
- 山东省济南市2025届中考数学真题(含答案)
- 2025-2030农业传感器网络部署模式与精准农业实践案例
- 接手烂尾项目的合同范本
- 物业客服人员培训
- 2025-2026学年地质版(2024)小学体育与健康二年级(全一册)教学设计(附目录P173)
- 茶百道培训课件
- 2025至2030年中国制药装备行业市场全景分析及投资前景展望报告
- 2025北京京剧院招聘工作人员10人考试备考题库及答案解析
- 检修现场管理培训课件
评论
0/150
提交评论