程序四则运算表达式
字符串的四则运算
字符串的四则运算四则运算,最常⽤的当然是逆波兰⽅法,现将表达式由中缀表达式转化为后缀表达式,然后再使⽤栈计算即可。
这两步下来,估计没有三四百⾏代码是实现不了的。
中缀表达式转前缀后缀表达式将中缀表达式转换为后缀表达式的算法思想:数字时,加⼊后缀表达式;运算符:a. 若为 '(',⼊栈;b. 若为 ')',则依次把栈中的的运算符加⼊后缀表达式中,直到出现'(',从栈中删除'(' ;c. 若为除括号外的其他运算符,当其优先级⾼于除'('以外的栈顶运算符时,直接⼊栈。
否则从栈顶开始,依次弹出⽐当前处理的运算符优先级⾼和优先级相等的运算符,直到⼀个⽐它优先级低的或者遇到了⼀个左括号为⽌。
⾼优先级可以压迫低优先级!⼈⼯实现转换这⾥我给出⼀个中缀表达式:a+b*c-(d+e)第⼀步:按照运算符的优先级对所有的运算单位加括号:式⼦变成了:((a+(b*c))-(d+e))第⼆步:转换前缀与后缀表达式前缀:把运算符号移动到对应的括号前⾯,则变成了:-( +(a *(bc)) +(de)) ,把括号去掉:-+a*bc+de 前缀式⼦出现。
后缀:把运算符号移动到对应的括号后⾯,则变成了:((a(bc)* )+ (de)+ )- ,把括号去掉:abc*+de+- 后缀式⼦出现。
⽐如:计算(2 + 1) * (13 + 5)转换后得:((2+1)*(13+5)) -> ((2 1) + (13 5) +) * -> 2 1 + 13 5 + *这⾥把后缀表达式存储到vector<string>中,实现栈的计算,如下:int cal(int num1, int num2, string tag){if ("+" == tag){return num1 + num2;}else if ("-" == tag){return num1 - num2;}else if ("*" == tag){return num1*num2;}else{return num1 / num2;}}int evalRPN(vector<string> &tokens) {int result = 0;stack<int> nums;for (int i = 0; i<tokens.size(); i++){string tag = tokens[i];if (tag != "+"&&tag != "-"&&tag != "*"&&tag != "/"){//这是⼀个数字nums.push(atoi(tag.c_str()));}else{//不是⼀个数字int num2 = nums.top();nums.pop();int num1 = nums.top();nums.pop();result = cal(num1, num2, tag);nums.push(result);}}return result=nums.top();}实际中遇到的笔试题是这样的,有字符串表⽰的⼀个四则运算表达式,要求计算出该表达式的正确数值,⽐如:5+17*8-4/2。
第一讲 四则运算
C 语言程序设计第一讲四则运算程序举例:<1>长方形的长与宽分别为 25,12求周长?main(){printf(“%d\n”,(25+12)*2);}<2>求23*5的积是多少?main(){ printf(“%d”,23*5);}<3>求(1/2+1/3+1/4)*(1/5+1/6)的值。
main(){float a,b,c;a=1/2.0+1/3.0+1/4.0;b=1/5.0+1/6.0;c=a*b;printf(“c=%f \n”,c);}<4>巳知圆的半径是7.6求圆的周长?main() /*主函数.程序从这里开始*/{float a,r; /*定义单精度实型变量*/r=7.6; s=2*3.14*r; /*進行运算*/printf(“%f \n”,s); / *打印周长*/}<5>打印字符串:This is a book.main(){printf(“This is a book.”);}<6>打印小队旗.main(){printf(“A\n”);pri ntf(“I*\n”);printf(“I***\n”);printf(“I*****\n”);printf(“I\n”);printf(“I\n”);printf(“I\n”);}注: ①任何程序都以main()开头.②:任何程序都有函数体.用{}括起来.程序语法解释<1> 什么是程序?程序是为做一件亊预先写岀的符合逻辑的详细计划或工作过程。
<2> 什么是函数?是可以完成某一工作的程序模块.有接受任务与数据,并执行任务,返回结果的功能<3> 什么是函数体?在一对括号”{ }”里面的内容称为函数体.<4> 什么是C语言的语句?语句是实现函数功能的最小功能单元.函数体内,毎行由分号结束的都是语句.<5> 函数体一般由三部分组成:{①定义变量部分.②数据处理部分.③输岀结果部分.}<6> 在程序3中:哪是定义变量的语句?哪些是数据处理的语句?哪一行是输岀结果的语句?<7>定义变量类型与输岀格式必须相匹配:①int →%d ②long→%ld ③float→%f④double→%lf⑤char→%c ⑥char→%s<8> 算术运算符与赋値运算符的介绍:①”( )” 括号运算符.②”+ +” ; ”――”自增加1,自减减1③“*”;”/”;”%”乘除运算符 .④“+”;”-“加减运算符 .⑤“=”赋值运算符.运算符优先级别:①→②→⑶→④→⑤.而赋值运算符⑥优先级别最低.<9> 什么是变量?程序中可以攺变的量叫变量..在C语言中变量必须先定义后使用. 定义方法如下:①int a , b; /*定义a, b为整型变量.*/②float c ,d; /*定义为单精度实型变量.*/③long e, f; /*定义e ,f为长整型变量*/.④double;g,h; /*定义为双精度实型量*/注:变量名要用小写字母表示(待详讲).<10>为什么要先定义变量类型.......再使用?因它关系到为变量分配内单元数及取数范围.如定义不正确,会影响数据运算的正确性.<11> 各种类型变量佔内存的宇节数:①char占1个字节.②int占2个字节.③long占4个字节④float占4个字节⑤double占8个字节.<12> 各种类型变量的取数范围:①char: - 128←→127②int: -32768←→32767③long:-2147483648←→2147483647④float:3.4e-38←→3.4e+38⑤double:1.7e-308←→1.7+308程序实例:已知a=5000,b=200求a*b的积main(){ int a,b,c;a=5000;b=200;c=a*b;printf(“c=%d\n”,c);}运行结果是错误的.上面的程序作如下修攺:main(){long a,b,c;a=5000;b=200;c=a*b;prinnf(“c=%ld\n”,c);}运行结果是正确的.观察襾个程序,为什么结果一个错一个正确?一:赋值语句(各种赋值形式)赋值语句由赋值表达式加一个分号构成.例如:a=2+3*6;是一个赋值语句.其中“=”不是等号而是赋值运算符.作用是將2+3*6的得数20送给変量a.二:输岀语句 (程序3为例)printf(“c=%f\n”,c);是输岀语句,作用是向屏幕输岀结果.printf是保留字.在括号中有双引号和旡双引号两部分,用逗号隔开.其中: “c=”是原样输岀.”\n”是光标換行.输岀时,%f是变量c中的数值的位置.....,“f”要求用实数形式输岀.并自动带6位小数.怎样输入程序并运行程序⑴点击相对应图标(TC)进入C语言集成环境.⑵在编辑窗口输入源程序(在上面大窗口).⑶按”F9”査检程序是否有语法错误.⑷按”Ctrl+F9”运行程序.⑸按”Alt+F5”察看运行结果.注:⑴要想输入第二个源程序,必须删除第一个程序后,再进行第二个源程序的输入.⑵如未见光标可按F6.按F6光标可以在上下窗口中来回移动.如发现有光带复盖菜单请按“Esc”键,即可去掉复盖的光带.存盘的方法⑴第一次存盘时,按F2会出现NONAME.C,删除此名再键入新程序名如:a1.c 回车即可.⑵程序修攺后,如再次存盘时,直接按f2则自动存盘.⑶如果想调岀已存盘的程序,可按F3.找到程序名回车即可.编程与上机练习题<1>求(64+5×4)+(85―5×13)的值.<2>求(1/2+1/3+1/4)+45*(23/111)的值.<3>已知某学生的平时成绩为95分,考试成绩为87.75分,求总评分.并保留一位小数.(总评分=平时分×40%+考分×60%)<4>求90,76,89三数和与平均数.<5>求127除以36的啇及余数.<6>打印平行四边形(大小自定).三: 键盘输入语句编程实例:巳知苹果2.5元一斤,香蕉2元一斤,请为售货员编一个自动收款程序.main(){float a,b,p,x,s; /*定义为实型変量*/a=2.5;b=2; /*两物品单价*/scanf(“%f%f”,&p,&x); /*输入斤数*/s=a*p+b*x; /*求应付款*/printf(“s=%.2f\n”,s); /*输出*/}本例的语法解释:⑴scanf(“%f%f”,&p,&x);是键盘输入语句.它在程运行过程中,输入两个数据到变量p和x所对应内存单元中.<2>在键盘输入语句中,変量前面要加地址符.用逗号隔开两个変量….<3>printf(“s=%.2f”,s);语句中的”%.2f”是要求用保留両位小数的实数形式输岀.⑷键盘输入语句输入数据的方法:(以买苹果4斤,香蕉2.5斤为例:)运行:输入: 4 2.5 ↙s=15.00若键盘输入语句改为:scanf(“%f, %f”, &p, &x);再次运行:输入: 4,2.5↙s=15.00注:特别注意键盘输入时的不同方法.注:如果不买其中一项,则此项输入0.四:条件分支语句编程实例:输入成绩,如>=60分,则打印”pass”,如<60分,则打印”fail”.<方法一>main(){float a;scanf(“%f”,&a);if(a<60)printf(“a=% .1f→fail\n”,a);if(a>59)printf(“a=% .1f→pass\n”,a);}运行: 再次运行:45 ↙ 80 ↙a= 45.0→ fail a=80.0→ pass方法二:main(){float a;scanf(“%f”,&a);if(a<60.0)printf(“a=%.1f→fail”,a);else printf(“a=% .1f→pass”,a);}运行: 再次运行:50 ↙ 80a=50.0→fail a=80.0→pass本例的语法解释:<1>分支语句有两种格式:.否则不执行后面的语句,语句可以是一条语句,也可以是多条语句.如果是多条语句时,必须用花括号括起来,构成一个复合语句.行语句.如果(表达式)为假时,执行语句2, 执行完后顺序执行下一条语句. 同理:语句1和语句2可以是一行语句,也可是复合语句......五条件运算符:( ?:)编程实例:键盘输入任意大小两亇整数,打印大数.main(){int a,b; scanf(“%d%d”,&a,&b);printf(“max=%d\n”,a>b ? a:b);}运行: 再次运行:24 15 ↙9 26 ↙max=24 max=26本例的语法解释:⑴在printf(“max=%d\n”,a>b ? a:b);中,a>b ? a : b 是条件运算符的实际应用.其意是如果a>b为真时打印a ,为假时则打b.⑵当if~else结构中是表达式语句时,就可用条件运算符” ? : ”来编程.上机注意亊项:⑴在上机编程旡特别要求时,都用小写字母⑵输入源程序时,要在”英文狀态”下输入.⑶在使用键盘输入语句时,要在变量前加地址符”&”.多个变量之间用逗号隔开。
利用正则表达式处理四则运算
利⽤正则表达式处理四则运算不久之前我写过⼀篇的⽂章,其中验证部分我使⽤了正则表达式,但计算部分还是依靠基本流程处理的。
后来想了想,计算是否也能使⽤正则表达式呢?再做⼀个逻辑表达式计算就没太⼤意思了,这次咱来试试四则运算。
我的基本思路是先乘除后加减,先运算式⼦中简单的乘除法例如:“2*5”,但“2*(3+4)”不必处理先,咱们先解决简单的。
然后处理简单的加减法,例如"3+4",同样涉及括号的先不处理。
最后去括号,但是只去⽆⽤的括号,例如“(3)”,这样⼀来连续的式⼦(例如:2*8+9/3)总是能化成“(19)”,这样最终被去掉括号变成“19”再与其他部分做运算。
只需要重复以上的部分最终就能完成运算了。
但其实其中还漏了⼀步,那就是做完乘除运算之后还有⼀些应该在加减之前先运算的没有被保护起来,例如:“(1/2+2*3+1)/2+2*3”做完乘除运算之后式⼦为“(0.5+6+1)/2+6”如果现在执⾏加减运算,由于“2+6”能够被匹配,所以会被先计算那样就错了。
所以先要把“(0.5+6+1)/2”作为⼀个整体保护起来,我第⼀想到的办法就是加括号即“((0.5+6+1)/2)+6”,这样就不会被匹配了。
但是⼜有⼀个问题:如何确定哪些位置需要加括号呢?⾸先要加括号的地⽅⼀定是相乘除的两个部分中刚好有⼀个是带括号的式⼦另⼀个却是普通的数字,不然它⼀定会在上⼀步中被消灭掉,或者两个部分都带有括号意味着他们不需要先计算,不需要理会,其次他们没有被括号包围。
如果⽤正则表达式来匹配似乎⽐较困难,原因是有括号的那⼀部分中可能有不确定的内层括号,不能简单的⽤“\(\S+\)”,否则就会出⼤乱⼦了。
那怎么办呢?想了很久,发现这并不是⼀种好的解决⽅法,我开始换⼀种思路,既然添加括号不⽅便,那么能不能不加括号却不会造成错误呢?答案是有!例如在“(0.5+6+1)/2+6”中,先计算括号内的简单加减式⽽不管外⾯的加减式,也就是在加减运算的正则表达式中⾸尾加上括号即可。
四则运算表达式求解
四则运算表达式求解四则运算表达式求解 这次写了⼀个能够实现简单四则运算(+,-,*,/,含括号)的⼩程序。
⾸先分析⼀下功能需求与限定吧。
需求与限定1. 输⼊四则运算表达式,要求⽤户输⼊其计算的结果,程序能够判断⽤户输⼊是否正确。
2. 算式输⼊的数据为正整数或者正分数,⽤户输⼊计算结果为整数或分数(分数以“a/b”的形式表⽰)。
3. 统计⽤户输⼊正确的答案个数以及错误的答案个数。
分析 ⾸先不难想到,程序的整体设计思路分为两部分,⼀部分是中缀表达式转换为后缀表达式,另⼀部分就是后缀表达式的计算。
但在实现的过程中还有⼀个难点需要注意,就是分数在整个程序运⾏过程中的存储以及计算。
由于输⼊的限定,分数⼀定是以“a/b”的形式表⽰的,所以我们可以将这种表⽰直接看做两个数相除的形式。
由此,解决了输⼊是分数的问题。
计算过程中的分数存储以及分数与整数的计算问题,我们可以通过将整数分数进⾏规格化的存储来解决,即:我们建⽴⼀个表⽰分数的结构体如下,将整数和分数都以该结构体的形式存储,其中numerator表⽰分⼦,denominator表⽰分母。
对于分数a/b的存储⽅式就是numerator = a,denominator = b,整数c的存储⽅式就是numerator = c, denominator = 1。
通过这样统⼀规范的存储就使得我们在整个计算的过程变得轻松的多了。
1 typedef long long ll;2struct num{3 ll numerator, denominator;4 num(){numerator = 0; denominator = 1;}5 num(int n) {numerator = n; denominator = 1;}6 num(int n,int d) {numerator = n; denominator = d;}78void operator = (num x)9 {10 numerator = x.numerator;11 denominator = x.denominator;12 }13 }; 实现过程 在实现之初,我们先给出需要的变量的定义,如下:1#define maxn 100523char nifix[maxn], post[maxn];4char ans[maxn];5int cnt_right, cnt_wrong;6bool error;7 num res, rst; 其中,nifix为输⼊的算式; post为转化后的后缀表达式; ans表⽰⽤户输⼊的结果; cnt_right, cnt_wrong分别表⽰⽤户回答正确的个数以及回答错误的个数; error标志程序运⾏过程中是否出错,如:输⼊的表达式不符合规范,出现除零的情况等; res表⽰程序计算出的算式答案; rst表⽰⽤户输⼊的答案转换为规范化的形式的结果。
四则运算表达式计算前序遍历
四则运算表达式计算前序遍历前序遍历是二叉树遍历的一种方式,它的遍历顺序是根节点->左子树->右子树。
在四则运算表达式中,我们可以通过前序遍历的方式来计算表达式的结果。
四则运算表达式由操作数和操作符组成,操作数表示参与运算的数字,而操作符表示运算的方式(如加、减、乘、除等)。
在前序遍历中,我们首先遇到的是根节点,在四则运算表达式中根节点即为操作符。
根据前序遍历的顺序,我们可以得到以下算法来计算前序遍历的四则运算表达式:1.初始化一个操作数栈和一个操作符栈。
2.从右向左遍历表达式,逐字符读入。
3.如果当前字符是操作数,将其放入操作数栈中。
4.如果当前字符是操作符,将其放入操作符栈中。
5.如果当前字符是右括号')',则将操作符栈中的操作符弹出,直到遇到左括号'('.弹出后,将弹出的操作符和操作数栈中的两个操作数进行计算,并将结果加入操作数栈中。
6.继续遍历表达式的下一个字符,直到表达式中的所有字符都遍历完毕。
7.最后,操作数栈中剩余的操作数即为表达式的计算结果。
下面以一个具体的表达式为例,来说明如何通过前序遍历计算四则运算表达式:表达式:(+ (* 4 5) (- 6 3))1.初始化操作数栈和操作符栈为空。
2.从右向左遍历表达式,首先遇到的是右括号')',压入操作符栈中。
3.继续遍历,遇到左括号'(',压入操作符栈中。
4.下一个字符是操作符'*',压入操作符栈中。
5.继续遍历,下一个字符是操作数'4',压入操作数栈中。
6.继续遍历,下一个字符是操作数'5',压入操作数栈中。
7.继续遍历,下一个字符是右括号')',弹出操作符栈中的操作符'*'。
8.弹出操作数栈中的两个操作数,即为'4'和'5',进行计算,得到结果'20',将结果'20'压入操作数栈中。
数据结构课程设计四则运算表达式求值(C语言版)
数据结构课程设计四则运算表达式求值(C语⾔版) 明⼈不说暗话,直接上,输⼊提取码z3fy即可下载。
⽂件中包含程序,程序运⾏⽂件,设计报告和测试样例,应有尽有,欢迎⼩伙伴们在中下载使⽤。
本课程设计为四则运算表达式求值,⽤于带⼩括号的⼀定范围内正负数的四则运算标准(中缀)表达式的求值。
注意事项:1、请保证输⼊的四则表达式的合法性。
输⼊的中缀表达式中只能含有英⽂符号“+”、“-”、“*”、“/”、“(”、“)”、“=”、数字“0”到“9”以及⼩数点“.”,输⼊“=”表⽰输⼊结束。
例如9+(3-1)*3.567+10/2=,特别是请勿输⼊多余空格和中⽂左右括号。
2、输⼊的中缀表达式默认限定长度是1001,可根据具体情况调整字符串数组的长度。
3、请保证输⼊的操作数在double数据类型范围内,单个数字有效数字长度不可超过15位。
本课程设计中操作数是C语⾔中的双精度浮点数类型。
4、本课程设计中的运算数可以是负数,另外如果是正数可直接省略“+”号(也可带“+”号)。
下⾯的程序正常运⾏需要在上⾯的百度⽹盘中下载相应⽂件,否则⽆法正常使⽤哦。
1/*本程序为四则运算表达式求值系统,⽤于计算带⼩括号的四则运算表达式求值。
2具体算法:3先将字符串处理成操作单元(操作数或操作符),再利⽤栈根据四则运算4的运算法则进⾏计算,最后得出结果。
*/56 #include<stdio.h>7 #include<ctype.h>8 #include<stdlib.h>9 #include<string.h>10 #include<stdlib.h>11 #include<ctype.h>1213const int Expmax_length = 1001;//表达式最⼤长度,可根据适当情况调整14struct Ope_unit15 {//定义操作单元16int flag;//=1表⽰是操作数 =0表⽰是操作符 -1表⽰符号单元17char oper;//操作符18double real;//操作数,为双精度浮点数19 };2021void Display();//菜单22void Instru(); //使⽤说明23int Check(char Exp_arry[]);24void Evalua(); //先调⽤Conver操作单元化,再调⽤Calculate函数计算结果并输出25int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[]);//将字符串处理成操作单元26int Isoper(char ch);//判断合法字符(+ - * / ( ) =)27int Ope_Compar(char ope1,char ope2);//操作符运算优先级⽐较28double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag);//⽤栈计算表达式结果29double Four_arithm(double x,double y,char oper);//四则运算3031int main()32 {33int select;34while(1)35 {36 Display();37 printf("请输⼊欲执⾏功能对应的数字:");38 scanf("%d",&select);39 printf("\n");40switch(select)41 {42case1: Evalua(); break;43case2: Instru(); break;44case0: return0;45default : printf("⽆该数字对应的功能,请重新输⼊\n");46 system("pause");47 }48 }49return0;50 }5152int Check(char Exp_arry[])53 {//检查是否有⾮法字符,返回1表⽰不合法,0表⽰合法54int Explength=strlen(Exp_arry),i;55for(i=0;i<Explength;i++)56 {57if(!Isoper(Exp_arry[i]) && Exp_arry[i] != '.' && !isdigit(Exp_arry[i]))58return1;59if(isdigit(Exp_arry[i]))60 {61int Dig_number=0,Cur_positoin=i+1;62while(isdigit(Exp_arry[Cur_positoin]) || Exp_arry[Cur_positoin]=='.')63 {64 Dig_number++;65 Cur_positoin++;66 }67if(Dig_number >= 16)//最多能够计算15位有效数字68return1;69 }70 }71return0;72 }7374void Evalua()75 {//先调⽤Conver函数将字符串操作单元化,再调⽤Calculate函数计算结果并输出76char Exp_arry[Expmax_length];77int flag=0;//假设刚开始不合法,1表达式合法,0不合法78struct Ope_unit Opeunit_arry[Expmax_length];7980 getchar();//吃掉⼀个换⾏符81 printf("请输⼊四则运算表达式,以=结尾:\n");82 gets(Exp_arry);83 flag=Check(Exp_arry);84if(flag)85 printf("该表达式不合法!\n");86else87 {88int Opeunit_count = Conver(Opeunit_arry,Exp_arry);89double ans = Calculate(Opeunit_arry,Opeunit_count,flag);90if(flag)91 {92 printf("计算结果为:\n");93 printf("%s%lf\n",Exp_arry,ans);94 }95else96 printf("该表达式不合法!\n");97 }98 system("pause");99 }100101int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[])102 {//将字符串操作单元化103int Explength=strlen(Exp_arry);104int i,Opeunit_count=0;105for(i=0;i<Explength;i++)106 {107if(Isoper(Exp_arry[i]))//是操作符108 {109 Opeunit_arry[Opeunit_count].flag=0;110 Opeunit_arry[Opeunit_count++].oper=Exp_arry[i];111 }112else//是操作数113 {114 Opeunit_arry[Opeunit_count].flag=1;115char temp[Expmax_length];116int k=0;117for(; isdigit(Exp_arry[i]) || Exp_arry[i]=='.' ;i++)118 {119 temp[k++]=Exp_arry[i];120 }121 i--;122 temp[k]='\0';123 Opeunit_arry[Opeunit_count].real=atof(temp);//将字符转化为浮点数124125//负数126if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0127 && Opeunit_arry[Opeunit_count-1].oper=='-')128 {129 Opeunit_arry[Opeunit_count-1].flag = -1;130 Opeunit_arry[Opeunit_count].real *= -1;131 }// -9132if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0133 && Opeunit_arry[Opeunit_count-1].oper=='-' && Opeunit_arry[Opeunit_count-2].flag==0 134 && Opeunit_arry[Opeunit_count-2].oper !=')')135 {136 Opeunit_arry[Opeunit_count-1].flag = -1;137 Opeunit_arry[Opeunit_count].real *= -1;138 }// )-9139140//正数141if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0142 && Opeunit_arry[Opeunit_count-1].oper=='+')143 {144 Opeunit_arry[Opeunit_count-1].flag = -1;145 }// +9146if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0147 && Opeunit_arry[Opeunit_count-1].oper=='+' && Opeunit_arry[Opeunit_count-2].flag==0148 && Opeunit_arry[Opeunit_count-2].oper !=')')149 {150 Opeunit_arry[Opeunit_count-1].flag = -1;151 }// )+9152 Opeunit_count++;153 }154 }155/*for(i=0;i<Opeunit_count;i++)156 {//查看各操作单元是否正确,1是操作数,0是操作符157 if(Opeunit_arry[i].flag == 1)158 printf("该单元是操作数为:%lf\n",Opeunit_arry[i].real);159 else if(Opeunit_arry[i].flag == 0)160 printf("该单元是操作符为:%c\n",Opeunit_arry[i].oper);161 else162 printf("该单元是负号符为:%c\n",Opeunit_arry[i].oper);163 }*/164return Opeunit_count;165 }166167double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag)168 {//根据运算规则,利⽤栈进⾏计算169int i,dS_pointer=0,oS_pointer=0;//dS_pointer为操作数栈顶指⽰器,oS_pointer为操作符栈顶指⽰器170double Dig_stack[Expmax_length];//操作数栈(顺序存储结构)171char Ope_stack[Expmax_length];//操作符栈172173for(i=0;i<Opeunit_count-1;i++)174 {175if( Opeunit_arry[i].flag != -1 )176 {177if(Opeunit_arry[i].flag)//是操作数178 {179 Dig_stack[dS_pointer++]=Opeunit_arry[i].real;//⼊操作数栈180//printf("%lf\n",Digit[dS_pointer-1]);181 }182else//是操作符 + - * / ( )183 {184//操作符栈为空或者左括号⼊栈185if(oS_pointer==0 || Opeunit_arry[i].oper=='(')186 {187 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;188//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);189 }190else191 {192if(Opeunit_arry[i].oper==')')//是右括号将运算符⼀直出栈,直到遇见左括号193 {194 oS_pointer--;//指向栈顶195 dS_pointer--;//指向栈顶196while(Ope_stack[oS_pointer] != '(' && oS_pointer != 0)197 {198 Dig_stack[dS_pointer-1] = Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 199 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈200201 dS_pointer--;//前⼀个操作数出栈202//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);203 }204 oS_pointer--;//左括号出栈205206 oS_pointer++;//恢复指向栈顶之上207 dS_pointer++;208 }209else if(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer-1]))//和栈顶元素⽐较210 {211 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;212//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);213 }214else//运算符出栈,再将该操作符⼊栈215 {216 oS_pointer--;//指向栈顶217 dS_pointer--;//指向栈顶218while(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer])==0 && oS_pointer != -1) 219 {//当前操作符⽐栈顶操作符优先级⾼220 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 221 Ope_stack[oS_pointer--]);222 dS_pointer--;223//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);224 }225 oS_pointer++;//恢复指向栈顶之上226 dS_pointer++;227 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;228 }229 }230 }231 }232 }233/*for(i=0;i<oS_pointer;i++)234 printf("操作符栈%oS_pointer\Ope_u_count",Operator[i]);235 for(i=0;i<dS_pointer;i++)236 printf("操作数栈%lf\n",Digit[i]);*/237 oS_pointer--;//指向栈顶元素238 dS_pointer--;//指向栈顶元素239while(oS_pointer != -1)240 {241 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 242 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈243 dS_pointer--;//前⼀个操作数出栈244//printf("操作数栈顶元素为%lf\Ope_u_count",Digit[dS_pointer]);245 }246//printf("%dS_pointer,%dS_pointer\n",oS_pointer,dS_pointer);247if(oS_pointer==-1 && dS_pointer==0)248 flag=1;//为1表⽰表达式合法249return Dig_stack[0];250 }251252int Ope_Compar(char ope1,char ope2)253 {//操作符运算优先级⽐较254char list[]={"(+-*/"};255int map[5][5]={//先⾏后列,⾏⽐列的运算级优先级低为0,⾼为1256// ( + - * /257/* ( */1,0,0,0,0,258/* + */1,0,0,0,0,259/* - */1,0,0,0,0,260/* * */1,1,1,0,0,261/* / */1,1,1,0,0 };262int i,j;263for(i=0;i<5;i++)264if(ope1==list[i]) break;265for(j=0;j<5;j++)266if(ope2==list[j]) break;267return map[i][j];268 }269270double Four_arithm(double x,double y,char oper)271 {//四则运算272switch(oper)//保证不含其它运算符273 {274case'+': return x+y;275case'-': return x-y;276case'*': return x*y;277case'/': return x/y;//y不能为0278default : return0;279 }280 }281282int Isoper(char ch)283 {//判断合法字符 + - * / ( ) =284if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='=')285return1;286return0;287 }288289void Display()290 {//打印菜单291 system("cls");292 printf("/******************************************************************************/\n");293 printf("\t\t 欢迎使⽤本四则运算表达式求值系统\n");294 printf("\n\t说明:建议请您先阅读使⽤说明,再输⼊相应的数字进⾏操作,谢谢配合!\n"); 295 printf("\n\t\t1 四则运算表达式求值\n");296 printf("\n\t\t2 使⽤说明\n");297 printf("\n\t\t0 退出\n");298 printf("/******************************************************************************/\n");299 }300301void Instru()302 {//打印使⽤说明303 FILE *fp;304char ch;305if( ( fp=fopen("使⽤说明.txt","r") ) == NULL)306 {307 printf("⽂件打开失败!\n");308 exit(0);309 }310for(; (ch = fgetc(fp)) != EOF; )311 putchar(ch);312 fclose(fp);313 printf("\n");314 system("pause");315 }。
ognl表达式 四则运算
ognl表达式四则运算
OGNL表达式是一种强大的表达式语言,它可以用于在Java应用程序中进行动态数据访问和操作。
其中包含了四则运算,即加、减、乘、除四种运算。
在OGNL表达式中,加法运算使用“+”符号表示,例如:
num1 + num2
这将返回num1和num2的和。
减法运算使用“-”符号表示,例如:
num1 - num2
这将返回num1减去num2的结果。
乘法运算使用“*”符号表示,例如:
num1 * num2
这将返回num1和num2的乘积。
除法运算使用“/”符号表示,例如:
num1 / num2
这将返回num1除以num2的结果。
除此之外,OGNL表达式还支持其他运算,如取模运算(“%”符号)和幂运算(“^”符号)等。
熟练掌握OGNL表达式的四则运算对于Java开发者来说是非常重要的。
- 1 -。
四则运算表达式计算前序遍历
四则运算表达式计算前序遍历摘要:一、前序遍历的定义与意义二、四则运算表达式计算的基本方法三、使用前序遍历解决四则运算表达式计算问题四、前序遍历在实际应用中的优势与局限五、总结正文:一、前序遍历的定义与意义前序遍历是一种二叉树遍历方式,也被称为先序遍历。
它遵循“根- 左-右”的顺序访问二叉树的节点。
在计算机科学中,前序遍历常用于表达式的计算,特别是四则运算表达式的计算。
通过对四则运算表达式进行前序遍历,可以轻松地实现表达式的求值。
二、四则运算表达式计算的基本方法四则运算表达式计算主要包括以下几个步骤:1.解析表达式:将表达式字符串转换为抽象语法树(AST)。
2.评估优先级:根据运算符的优先级,对AST 中的节点进行排序。
3.计算表达式:按照前序遍历的顺序,对AST 中的节点进行计算,得出最终结果。
三、使用前序遍历解决四则运算表达式计算问题前序遍历在四则运算表达式计算中的优势在于,它能够确保每个节点在计算过程中只被访问一次,避免了重复计算。
同时,前序遍历的顺序遵循了运算符的优先级,使得计算过程更加清晰易懂。
四、前序遍历在实际应用中的优势与局限前序遍历在四则运算表达式计算中的优势已经在上一个部分中提到。
然而,它也有一定的局限性。
例如,当表达式中存在括号时,前序遍历可能无法正确计算表达式的值。
在这种情况下,需要使用其他遍历方式,如中序遍历或后序遍历,来解决这个问题。
五、总结总的来说,前序遍历在四则运算表达式计算中起到了关键作用。
它不仅使得计算过程更加高效,还有助于理解表达式的内在逻辑。
Java实现四则运算表达式
四则混合运算的算符优先算法Java实现它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。
它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。
举例:(3 + 4) × 5 - 6 就是中缀表达式- × + 3 4 5 6 前缀表达式3 4 + 5 × 6 - 后缀表达式中缀表达式(中缀记法)中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。
中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。
对计算机来说,计算前缀或后缀表达式的值非常简单。
前缀表达式(前缀记法、波兰式)前缀表达式的运算符位于操作数之前。
前缀表达式的计算机求值:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
例如前缀表达式“- × + 3 4 5 6”:(1) 从右至左扫描,将6、5、4、3压入堆栈;(2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;(3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;(4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
可以看出,用计算机计算前缀表达式的值是很容易的。
将中缀表达式转换为前缀表达式:遵循以下步骤:(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;(2) 从右至左扫描中缀表达式;(3) 遇到操作数时,将其压入S2;(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:(4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;(5) 遇到括号时:(5-1) 如果是右括号“)”,则直接压入S1;(5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;(6) 重复步骤(2)至(5),直到表达式的最左边;(7) 将S1中剩余的运算符依次弹出并压入S2;(8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
简单的四则运算计算器程序
简单的四则运算计算器程序
实验目的与要求: 目的: 1、掌握类、构造函数/析构函数、栈等概念,掌握字符串操作; 2、步了解类的设计方法,初步了解词法分析、表达式求值的算符优先算法等 内容。 要求:
cout<<"程序错误,0作为除数出现!";
} else
a=a/b; }break; case '+':a=a+b;break; case '-':a=a-b;break; default:{}break; } Operand oper(a); sOperand.push(oper);
//cout<<"计算,并将结果压:"<<sOperand.getTop().get()<<"入栈\n";
char ch=temp[0]; double a,b; if(ch=='(') {
Operator oper('('); sOperator.push(oper);
//cout<<"符号:"<<sOperator.getTop().get()<<"入栈\n";
} else if(ch==')') {
//cout<<"计算,并将结果压:"<<sOperand.getTop().get()<<"入栈\n";
c语言循环实现计算机的四则运算
一、概述计算机是现代社会不可或缺的工具,而计算机的运算能力是其重要的功能之一。
C语言作为一种通用的高级语言,具有广泛应用的特点,在计算机编程中也扮演着重要的角色。
本文将介绍如何利用C语言的循环结构,实现计算机的四则运算功能,以及对应的代码实现。
二、C语言循环结构C语言提供了多种循环结构,包括for循环、while循环和do...while循环。
这些循环结构可以帮助程序实现重复执行某段代码的功能,非常适合用于实现四则运算中的重复计算过程。
1. for循环for循环是C语言中最常用的一种循环结构,其语法形式为:```cfor (初始化表达式; 判断表达式; 更新表达式){循环体;}```其中初始化表达式用于初始化循环变量,判断表达式用于判断循环是否继续执行,更新表达式用于更新循环变量的值。
利用for循环结构,可以方便地实现对变量进行增减的操作,从而实现四则运算中的加减乘除功能。
2. while循环while循环是C语言中另一种常见的循环结构,其语法形式为:```cwhile (判断表达式){循环体;}```while循环会在每次执行循环体之前判断条件表达式的真假,只有在条件为真时才会执行循环体,因此适用于实现需要满足特定条件才能进行计算的四则运算。
3. do...while循环do...while循环是C语言中的另一种循环结构,其语法形式为:```cdo{循环体;} while (判断表达式);```do...while循环先执行一次循环体,然后再判断是否继续执行循环体,因此适用于需要至少执行一次计算过程的四则运算。
三、C语言实现四则运算利用上述介绍的C语言循环结构,可以方便地实现计算机的四则运算。
下面将分别介绍如何利用循环结构实现加法、减法、乘法和除法运算,并给出相应的代码实现。
1. 加法运算加法运算是最基本的四则运算之一,其实现可以利用C语言的循环结构来实现。
下面是利用for循环实现加法运算的示例代码:```c#include <stdio.h>int m本人n(){int a = 3;int b = 5;int sum = 0;for (int i = 0; i < b; i++){sum++;}printf("d + d = d\n", a, b, sum);return 0;}```在这段代码中,利用for循环结构对变量sum进行了累加操作,从而实现了加法运算。
c++实现四则运算
c++实现四则运算
描述:读⼊⼀个只包含 +, -, *, / 的⾮负整数计算表达式,计算该表达式的值。
输出:计算结果,保留两位⼩数。
程序任务分为两部分:
⼀。
将输⼊的中缀表达式转换为后缀表达式,实现过程:
1.准备队列保存后缀表达式(计算后缀表达式时,需要从队⾸读取数据)
准备栈保存计算符,使⽤找调整计算顺序
2.读输⼊字符串,如果是数字,直接⼊后缀表达式队列;
如果是计算符号,当计算符号栈为空或当前符号优先级⼤于栈顶符号优先级,直接⼊栈。
否则依次弹出栈顶符号⼊后缀表达式队列,直到遇到优先级不⼩于当前的符号或栈空。
如果是(直接⼊栈,如果是)弹出符号栈中符号⼊后缀表达式队列,直到((不⼊队)
3.反复2过程直到读完所有字符串,若符号栈不为空,弹出其中所有元素⼊队
⼆。
计算后缀表达式:
计算栈
1.弹出队列元素,如果是数字,直接⼊栈,如果是操作符号,弹出栈顶两个数字计算。
P.S.第⼀个弹出数字是第⼆个数字,第⼆个弹出数字是第⼀个数字。
|temp1| 栈顶 temp2 - temp1 注意这⼀点,容易在减和除运算中出错
|--------|
|temp2|
|--------|。
JAVA四则运算算法
JAVA四则运算算法⼀、程序要求解析⼀般数学算式,实现简单的带括号的加减乘除运算。
⼆、基本思路前⾯两篇介绍了直接解析字符串和⽤数组容器辅助解析的两种⽅式,这次再介绍最常⽤的解析算法——解析后缀表达式(逆波兰表达式)。
三、逆波兰表达式及其得到算法1、逆波兰表达式也即后缀表达式,指的是不包含括号,运算符放在两个运算对象的后⾯,所有的计算按运算符出现的顺序,严格从左向右进⾏(不再考虑运算符的优先规则)。
(摘⾃百度),既然没了运算符的优先规则,那么计算机解析起来⾃然容易的多。
对于我们常见的表达式,称为中缀表达式,每个中缀表达式都有对应的后缀表达式。
如:中缀表达式:-2*(1+6/3)+4后缀表达式:-2 1 6 3 / + * 4 +(这⾥为了区分负号和减号,我在数字与数字、数字与符号之间都加了空格,⾄于怎么从中缀表达式得到后缀表达式,后⾯有介绍及参考程序)⽽在解析后缀表达式时,只需要遵守以下原则即可:从左往右遍历遇到数字直接放⼊容器遇到运算符,将最后两个数字取出,进⾏该运算,将结果再放⼊容器遍历结束后,容器中的数字即为运算结果按这个过程⾛下来,⾃然⽽然的想到⽤栈是最合适的。
现只需想办法由输⼊的中缀表达式转为后缀表达式即可完成解析。
2、由中缀表达式得到后缀表达式的算法由中缀表达式得到后缀表达式,只要遵守以下步骤即可:⾸先设置运算符的优先级(这样设置也是为了简化程序):”null” 栈顶若为空,假设优先级为0“(” 优先级设为1“+-” 优先级设为2“*/” 优先级设为3从左向右遍历中缀表达式遇到数字直接输出遇到符号遇到左括号,直接压栈遇到右括号,弹栈输出直到弹出左括号(左括号不输出)遇到运算符,⽐较栈顶符号,若该运算符优先级⼤于栈顶,直接压栈;若⼩于栈顶,弹栈输出直到⼤于栈顶,然后将改运算符压栈。
最后将符合栈弹栈并输出现根据这个原则,⼿动模拟⼀遍转换过程:还是以-2*(1+6/3)+4为例四、代码⼀环境:Eclipse Java EE IDE(Version: Oxygen.1a Release (4.7.1a))jdk1.8.0_131先写⼀个最基本的两位数四则运算⽅法,⽐较简单,没有写注释:private static double doubleCal(double a1, double a2, char operator) throws Exception {switch (operator) {case '+':return a1 + a2;case '-':return a1 - a2;case '*':return a1 * a2;case '/':return a1 / a2;default:break;}throw new Exception("illegal operator!");} 写⼀个获得优先级的⽅法:private static int getPriority(String s) throws Exception {if(s==null) return 0;switch(s) {case "(":return 1;case "+":;case "-":return 2;case "*":;case "/":return 3;default:break;}throw new Exception("illegal operator!");}将中缀表达式转变为后缀表达式:private static String toSufExpr(String expr) throws Exception {System.out.println("将"+expr+"解析为后缀表达式...");/*返回结果字符串*/StringBuffer sufExpr = new StringBuffer();/*盛放运算符的栈*/Stack<String> operator = new Stack<String>();operator.push(null);//在栈顶压⼈⼀个null,配合它的优先级,⽬的是减少下⾯程序的判断/* 将expr打散分散成运算数和运算符 */Pattern p = pile("(?<!\\d)-?\\d+(\\.\\d+)?|[+\\-*/()]");//这个正则为匹配表达式中的数字或运算符Matcher m = p.matcher(expr);while (m.find()) {String temp = m.group();if (temp.matches("[+\\-*/()]")) { //是运算符if (temp.equals("(")) { //遇到左括号,直接压栈operator.push(temp);System.out.println("'('压栈");} else if (temp.equals(")")) { //遇到右括号,弹栈输出直到弹出左括号(左括号不输出)String topItem = null;while (!(topItem = operator.pop()).equals("(")) {System.out.println(topItem+"弹栈");sufExpr.append(topItem+" ");System.out.println("输出:"+sufExpr);}} else {//遇到运算符,⽐较栈顶符号,若该运算符优先级⼤于栈顶,直接压栈;若⼩于栈顶,弹栈输出直到⼤于栈顶,然后将改运算符压栈。
c语言求解带括号的四则运算表达式
c语言求解带括号的四则运算表达式如何用C语言求解带括号的四则运算表达式在C语言中,我们可以使用栈来求解带括号的四则运算表达式。
栈是一种先入后出(Last-In-First-Out)的数据结构,对于表达式中的每一个运算符,我们都可以使用栈来保存其优先级。
下面是一步一步的解决方法。
第一步:定义运算符优先级在处理表达式时,我们需要知道每个运算符的优先级。
在C语言中,可以使用switch语句来定义每个运算符的优先级。
例如:cint getPriority(char op) {switch(op) {case '+':case '-':return 1;case '*':case '/':return 2;case '(':case ')':default:return 0;}}在这个函数中,我们将运算符+和-的优先级定义为1,将运算符*和/的优先级定义为2,而括号的优先级定义为0。
第二步:将表达式转换为后缀表达式后缀表达式是指将运算符放在操作数之后的表达式形式。
为了求解带括号的四则运算表达式,我们首先需要将其转换为后缀表达式。
具体的转换规则如下:1. 从左到右扫描表达式,如果遇到操作数,则直接将其输出。
2. 如果遇到运算符,则将其与栈顶的运算符比较优先级。
如果栈顶的运算符优先级大于等于当前的运算符,则将栈顶的运算符弹出并输出,直到栈顶的运算符优先级小于当前的运算符或者栈为空。
然后将当前的运算符压入栈中。
3. 如果遇到左括号,则直接将其压入栈中。
4. 如果遇到右括号,则将栈顶的运算符弹出并输出,直到遇到左括号为止。
左括号不输出。
例如,对于表达式"3 + 4 * ( 2 - 1 )",其转换为后缀表达式为"3 4 2 1 - * +"。
第三步:求解后缀表达式在将表达式转换为后缀表达式之后,我们可以使用栈来求解后缀表达式。
四则运算公式
四则运算公式四则运算(Arithmetic Operations)是一类基本的数学计算,它把数学表达式拆分成最小的计算单元,通过四种基本运算加以运算,从而实现一个数学问题的计算。
这四种基本运算由相应的符号:加+、减-、乘×、除÷来表示,它们的公式分别是:① 加法(Addition):a +b = c② 减法(Subtraction):a -b = c③ 乘法(Multiplication):a ×b = c④ 除法(Division):a ÷b = c其中,a, b和c代表数字。
加法运算是将两个数字的值相加,得到新的数字c。
比如1 + 2 = 3,则a=1,b=2,c=3。
减法运算是将第二个数字的值从第一个数字的值中减去,得到新的数字c。
比如3 - 2 = 1,则a=3,b=2,c=1。
乘法运算是将两个数字的值相乘,得到新的数字c。
比如4 × 2 = 8,则a=4,b=2,c=8。
除法运算是将第一个数字的值除以第二个数字的值,得到新的数字c。
比如16 ÷ 4 = 4,则a=16,b=4,c=4。
此外,还有一种基本四则运算叫做乘方(Exponentiation),它的公式是:a^b = c,其中a, b和c代表数字。
乘方运算是将第一个数字的值乘以第二个数字的值,得到新的数字c。
比如2^3 = 8,则a=2,b=3,c=8。
四则运算是常用的数学计算,它的历史可以追溯到古代中国的《九章算术》中。
它既可以独立使用,也可以组合使用,它的用法和准确性在学校普遍使用。
因此,学习四则运算可以让您更好地理解数学,完成各种数学计算。
四则运算汇编语言程序设计
安徽工程大学《汇编语言程序设计》大作业报告班级: XXXXX 学号: XXXXXXXX 完成人: XXXXXXX任课老师: XXXXXXX 时间: XXXXXXXXXX《汇编语言程序设计》大作业任务书大作业题目:四则运算程序程序功能要求:编写一个程序,每运行一次可执行程序,可以实现加减乘除四则运算。
计算器是最简单的计算工具,简单计算器具有加、减、乘、除四项运算功能。
1.设计目标运用汇编语言,制作一个计算的程序,实现简单计算器的一般功能,能够在DOS界面下进行简单的加、减、乘、除的简单计算。
程序应有操作提示、输入和输出。
自动闪烁光标,并提示输入信息。
输入正确的数值等符号后可以进行正确的运算,程序计算其结果值并输出。
程序无需查错功能,所输入的都是正确的四则运算表达式,并且表达式中运算分量均为无正负号整数,运算符为+、-、*、/,最后结果以十进制数表示。
且程序主界面需为一个由‘*’组成边框的矩形窗口。
2.软件设计2.1程序设计的基本思想主模块:首先提供一个主界面,提示用户按要求输入具体的数据和所要进行的操作,输入完毕后给出结果。
如果输入过程中发现非法输入,则立即给与提示,程序自动刷新界面,提示继续输入。
计算显示完毕后,按提示选择是否要继续计算,不选择继续则结束。
对屏幕上输入字符串的接受,为INPUT语句段,见源代码,主要是将数字和运算符分开存放。
MATCH子程序,子程序内有三次跳转,将运算符选择正确的语句进行计算。
由于操作符只有+、-、*、/,没有涉及到括号,不用考虑括号的匹配问题。
流程图如下:图1 主模块流程图子模块:完成对数据的进一步加工处理,转换格式并得出结果。
首先根据输入调用对应的“+”、“-”、“*”、“/”四个函数模块,这是本程序的核心模块,其他部分的一些小模块都是为这几个模块服务的,大致的流程图如下图2:图2 子模块流程图3.系统调试3.1测试目标(1)在屏幕上显示一个由‘*’组成边框的矩形窗口;(2)自动闪烁光标,并提示输入信息;(3)能够完成单项表达式的输入、显示和运算;(4)编制并调试出程序。
数据结构实验报告五—四则运算表达式求值
问题描述:四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。
一、需求分析:1、本程序是利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。
2、输入输出格式:输入格式:在字符界面上输入一个中缀表达式,回车表示结束。
请输入表达式:输入一个中缀表达式输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
逆波兰表达式为:输出逆波兰表达式运算结果为:输出运算后的结果3、测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+二、概要设计:抽象数据类型二叉树类BiTree算法的基本思想根据题目要求,利用栈计算,和二叉树存储,来计算表达式该算法的基本思想是:先利用栈进行计算,然后用二叉树进行存储,和实验三算法一样来计算逆波兰表达式的值程序的流程程序由三个模块组成:(1)输入模块:输入一个运算式(2)计算模块:利用栈进行表达式的计算,二叉树来存储。
(3 )输出模块:屏幕上显示出后缀表达式和运算结果。
三、详细设计物理数据类型程序含有两个类,其中栈不再赘述,另一个类为二叉树class BiTree 包含私有成员struct BiTreeNode,根节点BiTreeNode *T;索引index; int number_of_point 优先级比较函数 compare(char a,char b);生成树的函数void InorderCreate(BiTreeNode *&T,char str[30][10],int start,int end);判断数字函数bool IsNumber(char a);求值函数double Operate(BiTreeNode *T);还有显示后缀表达式的函数void display(BiTreeNode *T) ;而公有成员函数则是对私有函数的重载,为方便使用,因为函数中普遍使用了递归的算法。
四则运算表达式的语法分析
四则运算表达式的语法分析四则运算表达式的语法分析本⽂参考⾃的《》。
之前有《》也是参考⾃《》。
通过语法规则表达操作符的优先级。
四则运算表达式的语法为:1.Term = <数字> | “(”Exp”)”2.Factor = Term ((“*” | “/”) Term)*3.Exp = Factor ((“+” | “-”) Factor)*根据语法写代码。
这⾥不对四则运算表达式求值,⽽是将其转换为等价的Lisp表达式,然后输出。
具体的代码如下:// 四则运算表达式的语法分析——⽣成LISP表达式#include <iostream>#include <string>using namespace std;// 表达式结构体struct Expression{bool IsNumber; // 是否是数字int Number; // 数字内容,只有当Isnumber = true的时候有效char Operator; // 操作符,只有当IsNumber = false的时候有效Expression* Left; // 左表达式,只有当IsNumber = false的时候有效Expression* Right; // 右表达式,只有当IsNumber = false的时候有效Expression(int aNumber){IsNumber = true;Number = aNumber;Operator = 0;Left = 0;Right = 0;}Expression(char aOperator, Expression* aLeft, Expression* aRight){IsNumber = false;Number = 0;Operator = aOperator;Left = aLeft;Right = aRight;}// 析构~Expression(){if (Left != 0){delete Left;Left = 0;}if (Right != 0){delete Right;Right = 0;}}void PrintLISP(){if (IsNumber){Left->PrintLISP();cout << "";Right->PrintLISP();cout << ")";}}};struct Exception{int Start; // 错误位置string Error; // 错误信息Exception(int aStart, const string& aError){Start = aStart;Error = aError;}};// 检测是否是空⽩符bool IsBlank(char ch){return ch == '' || ch == '\t';}// 检测Text是否是Stream从pos起始的开头// 如果是,则将pos前移Text.size()个字符,且返回true// 否则pos保持不变,返回false// 对于pos后的空⽩符忽略bool IsPrefix(const string& Stream, int& pos, const string& Text) {int read = pos; // 设置真实游标// 过滤空格while (IsBlank(Stream[read])){++read;}if (Stream.substr(read, Text.size()) == Text){pos = read + Text.size();return true;}else{return false;}}// 检测Stream从pos开头是否是数字Expression* GetNumber(const string& Stream, int& pos){int Result = 0;bool GotNumber = false;int read = pos;while (IsBlank(Stream[read])){++read;}while (true){char ch = Stream[read];if (ch >= '0' && ch <= '9'){Result = Result * 10 + ch - '0';GotNumber = true;++read;}else{break;}}if (GotNumber)throw Exception(read, "此处需要表达式"); // 不仅仅是需要数字}}Expression* GetTerm(const string& Stream, int& pos);Expression* GetFactor(const string& Stream, int& pos);Expression* GetExp(const string& Stream, int& pos);// 检测Stream从pos起始是否是⼀个Term// 实现语法1:Term = <数字> | “(”Exp”)”Expression* GetTerm(const string& Stream, int& pos){try{return GetNumber(Stream, pos);}catch (Exception& e){int read = pos;// 检测左括号if (IsPrefix(Stream, read, "(")){// 检测表达式Expression* Result = GetExp(Stream, read);if (IsPrefix(Stream, read, ")")){// 如果使⽤右括号结束,则返回结果pos = read;return Result;}else// 否则抛出异常{delete Result;Result = 0;throw Exception(read, "此处需要右括号");}}else{throw e; // 这⾥要求GetNumber函数中抛出的异常信息为“需要表达式”,⽽⾮“需要数字” // 或者:// throw Exception(read, "此处需要数字或左括号");}}}// 检测Stream从pos起始,开头是否是Factor// 实现语法2:Factor = Term ((“*” | “/”) Term)*Expression* GetFactor(const string& Stream, int& pos){int read = pos;Expression* Result = GetTerm(Stream, read);while (true){char Operator = 0;if (IsPrefix(Stream, read, "*")){Operator = '*';}else if (IsPrefix(Stream, read, "/")){Operator = '/';}else{break;}if (Operator){// 如果是乘除号,则获得下⼀个Termtry{Result = new Expression(Operator, Result, GetTerm(Stream, read));}catch (Exception& e){pos = read;return Result;}// 检测Stream从pos起始,开头是否是⼀个Exp// 实现语法3:Exp = Factor ((“+” | “-”) Factor)*Expression* GetExp(const string& Stream, int& pos){int read = pos;Expression * Result = GetFactor(Stream, read);while (true){char Operator = 0;if (IsPrefix(Stream, read, "+")){Operator = '+';}else if (IsPrefix(Stream, read, "-")){Operator = '-';}else{break;}if (Operator != 0){// 如果是加减号,则获得下⼀个Factortry{Result = new Expression(Operator, Result, GetFactor(Stream, read)); }catch (Exception& e){delete Result;Result = 0;throw e;}}}pos = read;return Result;}int main(){while (true){string Stream;cout << "输⼊⼀个表达式:" << endl;getline(cin, Stream);int pos = 0;if (IsPrefix(Stream, pos, "exit")){break;}pos = 0;try{Expression* exp = GetExp(Stream, pos);while (pos < Stream.size() && IsBlank(Stream[pos])){++pos;}if (pos < Stream.size()){delete exp;exp = 0;throw Exception(pos, "发现多余的字符");}else{exp->PrintLISP();cout << endl << endl;catch (Exception& e){cout << "发⽣错误" << endl;cout << "错误位置:" << e.Start << endl;cout << "错误信息:" << e.Error << endl;cout << endl;}}return0;}上述四则运算表达式语法分析程序中的数据结构有:Expression结构体和Exception结构体。
C++四则运算表达式求值算法
u 这里定义了两个构造函数,不带参数的默认 m_string 为空,带 string 类型
参数的将参数值赋予成员变量 m_string,此外还定义了赋值运算符“=”,
目 的是将一个表达式字符串 赋予 成员变量 m_string 。 因此 生 成一个 ExpressionType 的对象可以有如下两种形式: ExpressionType expr(“(2.99-4.32)*(90.8-78.66)+78.0/3.14”); 或者 ExpressionType expr; Expr = “(2.99-4.32)*(90.8-78.66)+78.0/3.14”; u DivideExpressionToItem(): 私有成员函数,返回值是一个 string 类型的 队列。其功能是将原始的中缀表达式中的操作数、操作符以及括号按顺序以 字符串的形式分解出来,然后保存在一个队列中(队列的操作规则是先进先 出)。 u ChangeToSuffix(): 私有成员函数,返回值是一个 string 类型的栈。其功 能是将队列中表示原始表达式各项的字符串调整顺序,转换成后缀表达式的 顺序,并处理掉括号,然后保存在一个栈中(栈的操作规则是先进后出)。 u IsWellForm():私有成员函数,返回 bool 值。其功能是判断原始表达式中的 括号是否匹配,如果匹配返回 true,否则返回 false。 u Size():返回原始表达式所包含的字节数。 u Calculate(): 公有成员函数,返回 double 类型的值。其功能是计算转换后 的后缀表达式的值,即原始中缀表达式的值。
abc然后分别按从左到右放入栈中如果碰到操作符就从栈中弹出两个操作数进行运算最后再将运算结果放入栈中依次进行直到表达式放入栈中然后碰到操作符则从栈中弹出的运算并将其结果d假设为放入栈中最后是操作符所以再弹出进行dc运算并将其结果再次放入栈中此时表达式结束则栈中的元素值就是该表达式最后的运算结果
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
'<','<','<','<','<','\1','<','\1','<','\1','='
};
int i[2], j=0, TreatB=0;
do
case '=':
s++;
break;
default:
error(order);
return false;
}
}
do NumPop(szA[i]);
while (szA[i++]!=',');
szA[--i]='\0';
strrev(szA);
b=atof(szA);
//从num栈中获取第二个操作数
OpePush(*s++);
if (*s=='+') s++;
else if (*s=='-')
{
s++;
OpePush('-');
{
if (p>=100) return false;
ope[p++]=a;
return true;
}
bool CalcInfixExp::OpePop(char &a)
{
if (p==0) return false;
a=ope[--p];
'>','>','>','>','<','>','<','>','<','>','>',
'<','<','<','<','<','=','\3','\1','\3','\1','\1',
'>','>','>','>','\2','>','>','>','>','>','>',
//计算
switch (f)
{
case '+': c=a+b; break;
case '-': c=a-b; break;
case '*': c=a*b; break;
return true;
}
int main()
{
CalcInfixExp s;
double result;
char a[100];
printf("请输入四则运算表达式\n");
while (gets(a))
if (s.calc(result, a))
'<','<','<','<','<','\1','<','=','\3','\1','\1',
'>','>','>','>','\2','\3','=','>','>','>','>',
'<','<','<','<','<','\1','<','\1','<','=','\1',
void error(char n);
char GetOrder(char a, char b);
bool NumPush(const char &a);
bool NumPop(char &a);
bool OpePush(const char &a);
{
switch (a)
{
case '+': i[j]=0; break;
case '-': i[j]=1; break;
case '*': i[j]=2; break;
case '/': i[j]=3; break;
while (szA[i++]!=',' && PopRight);
if (PopRight) NumPush(',');
szA[--i]='\0';
strrev(szA);
a=atof(szA);
case '\2': printf("右括号与左括号间没有运算符\n"); break;
case '\3': printf("低级括号内包含高级括号\n"); break;
case '\4': printf("运算符过多\n");
}
}
char CalcInfixExp::GetOrder(char a, char b)
case '/': c=a/b; break;
}
gcvt(c, 16, szA);
i=strlen(szA)-1;
if (szA[i]=='.') szA[i]='\0';
}while (p!=0);
result=atof(num);
return true;
}
void CalcInfixExp::error(char n)
{
switch (n)
{
case '\1': printf("括号不匹配\n"); break;
if (q==0)
{
error('\4'); //num栈已空
return false;
}
NumPop(szA[i]);
printf("%lg\n", result);
return 0;
}
case '(': i[j]=4; break;
case ')': i[j]=5; break;
case '[': i[j]=6; break;
case ']': i[j]=7; break;
case '{': i[j]=8; break;
NumPush(',');
}
else
{
OpePop(f);
switch (order=GetOrder(f, *s))
{
case '<':
OpePush(f);
{
if (q>=100) return false;
num[q++]=a;
return true;
}
char CalcInfixExp::calc(double &result, const char *s)
{
bool PopRight;
char f, szA[20], order;
bool OpePop(char &a);
private:
int p, q;
char ope[100];
char num[100];
};
CalcInfixExp::CalcInfixExp()
{
p=q=0;
};
bool CalcInfixExp::NumPush(const char &a)
//把计算结果压入栈
i=0;
do NumPush(szA[i]);
while (szA[++i]!='\0');
NumPush(',');
break;
int i;
double a, b, c;