C++四则运算表达式求值算法
C语言-四则运算
四则运算姓名:学号:班级:1.功能结构图2.程序功能进行整数的加减乘除和求模运算。
程序采用随机产生1~100的两个数进行运算每种运算有10个题目用户输入对应的答案程序提示答案的对错最后统计正确率。
每次给出两次答题机会。
3.程序流程图4.函数列表及功能5.源程序代码#include<stdio.h>#include<stdlib.h>#include<time.h>#define N 10int f(int a,int b){ //自定义函数int result;result=a+b;return result;}int f1(int a,int b){int result;result=a-b;return result;}int f2(int a,int b){int result;result=a*b;return result;}int f3(int a,int b){int result;result=a*b/b;return result;}int mod(int a,int b){int result;result=a%b;return result;}int main(){int a,b,res,ans;int i,count;int op,c;srand((unsigned)time(NULL)); while(1){printf("\n---加减乘除运算练习系统---\n");printf("1.加法运算\n");printf("2.减法运算\n");printf("3.乘法运算\n");printf("4.除法运算\n");printf("5.求模运算\n");printf("6.混合运算\n");printf("0.退出练习\n");printf(" 请输入数字0~6:");scanf("%d",&op); //输入相应数字进行练习switch(op){case 1:printf("--请进行加法运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%100+1;b=rand()%100+1;res=f(a,b); //调用加法函数printf("%d+%d=",a,b);scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 2:printf("--请进行减法运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%100+1;b=rand()%100+1;res=f1(a,b); //调用减法函数printf("%d-%d=",a,b);scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 3:printf("--请进行乘法运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%100+1;b=rand()%100+1;res=f2(a,b); //调用乘法函数printf("%d*%d=",a,b);scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 4:printf("--请进行除法运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%10+1;b=rand()%10+1;res=f3(a,b); //调用除法函数printf("%d/%d=",a*b,b);scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 6:printf("--请进行混合运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%100+1;b=rand()%100+1;c=rand()%5; //产生0~4的随机数{switch(c) //随机出现进行混合运算{case 0:printf("%d+%d=",a,b);res=f(a,b);break;case 1:printf("%d-%d=",a,b);res=f1(a,b);break;case 2:printf("%d*%d=",a,b);res=f2(a,b);break;case 3:a=a%10+1;b=b%10+1;printf("%d/%d=",a*b,b);res=f3(a,b);break;case 4:printf("%d%%%d=",a,b);res=mod(a,b);break;}}scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 5:printf("--请进行求模运算--\n");count=0;for(i=1;i<=N;i++){a=rand()%100+1;b=rand()%100+1;res=mod(a,b); //调用求模函数printf("%d%%%d=",a,b);scanf("%d",&ans); //输入数值if(ans==res){printf("Very Good!\n");count++;}else{printf("wrong! 请重新输入\n");scanf("%d",&ans);if(ans==res)printf("Very Good!\n");elseprintf("Wrong Answer!\n");}}printf("***正确率为%.0f%%***\n",100.0*count/N); break;case 0:goto END; //转到结束}}END:printf("---练习结束---\n");return 0;}6程序运行图选取起始和加法混合运算程序开始显示6种练习方式输入0为退出。
数据结构课程设计四则运算表达式求值(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 }。
四则运算和运算定律--知识点整理
四则运算和运算定律知识点整理四则运算是指加法、减法、乘法、除法的计算法则.一级运算:加、减.二级运算:乘、除.运算顺序:先乘除后加减,如果有括号就先算括号内的,然后再算括号外的。
先算小括号,然后算中括号、大括号.两级运算,先算高一级后算低一级。
即先算乘除后算加减.(同一级运算中,计算顺序是从左到右)1、如果只有加和减或者只有乘和除,从左往右计算。
(同一级计算)2、如果同时有一级、二级运算,先算二级运算.即先算乘除后算加减。
3、如果有括号,要先算括号里的数,(不管什么级都要先算)。
4、关于括号里的计算:先算小括号,然后算中括号、大括号,括号中也是先算二级,再算一级.运算定律1、加法交换律:a+b=b+a有两个加数相加,交换加数的位置,和不变,这叫做加法交换律。
2、加法结合律:a+b+c=(a+b)+c=a+(b+c)三个数相加,先把前两个数相加,再和第三个数相加,或者先把后两个数相加,在和第一个数相加,和不变,这叫做加法结合律。
3、减法的性质:a—b—c=a—(b+c)一个数连续减去两个数,可以用第一个数减轻后面两个数的和,差不变,这作减法的性质.4、乘法交换律:a×b=b×a两个数相乘,交换加数的位置,积不变,这叫做乘法的交换律。
5、乘法结合律:a×b×c=(a×b)×c=a×(b×c)三个数相乘,先把前两个数相乘,在和第三个数相乘,或者先把后两个数相乘,再和第一个数相乘,积不变,这叫做乘法的结合律.6、乘法分配律:(a+b)×c=a×c+b×c两个数的和与第三个数相乘,等于把这两个数分别与这个数相乘,再把它们的积相加起来,积不变,这叫做乘法分配律.7、除法的性质:a÷b÷c=a÷(b×c)一个数连续除以两个数,等于一个数除以两个数的积,商不变,这叫做除法的性质。
C++四则运算表达式求值算法
赋予 str,再将 str 推入队列,并将 str 赋予空值,依次循环进行直
到扫描 m_string 完成。其具体实现代码如下:
queue<string> ExpressionType::DivideExpressionToItem() {
类 ExpressionType 的定义包含了三个头文件<string>、<stack>
以及<queue>,这是标准模板库里现成的东西,直接拿来用就行了,
不必再自己写 栈和队列, 它们都 在 std 命名空间里 。 下面对类
ExpressionType 的成员作介绍:
u m_string: 私有成员变量,字符串类型。主要用于存储表示原始中缀表达式
推入栈 stack_A 中,然后再将 str 推入栈 stack_B 中。 ⑤除了上述情况 外就只剩下操作数 了,操作数 就可以 直接推 入栈 stack_A 中。注意整个过程中栈 stack_B 中的元素只能是如下几种: “(”、“+”、“-”、“*”、“/”,而最终栈 stack_A 保存的是后缀表达式, 只有操作数和操作符,如下图所示:
的字符串。
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 类型的值。其功能是计算转换后 的后缀表达式的值,即原始中缀表达式的值。
C语言实现大数四则运算
C语⾔实现⼤数四则运算⼀、简介众所周知,C语⾔中INT类型是有限制,不能进⾏超过其范围的运算,⽽如果采⽤float类型进⾏运算,由于float在内存中特殊的存储形式,⼜失去了计算的进度。
要解决整个问题,⼀种解决⽅法是通过字符串数组实现数据的存储,然后实现它们之间四则运算的函数。
⼆、数据结构为了实现字符数组之间的运算,要考虑数值的正负性,数字的长度以及具体存储的数字typedef struct num{int len; //数值长度char symbol; //数字正负形int number[LEN]; //数组}NUM,*SNUM;三、函数整个程序使⽤了⼀下的函数SNUM expToNum(char exp[]);//将输⼊字符串转换为对应结构体void reverse(int a[],int len);//数组逆序int compareAbs(SNUM left,SNUM right);//⽐较两数绝对值⼤⼩SNUM anti_add(SNUM left,SNUM right);//元加法SNUM anti_sub(SNUM left,SNUM right);//元减法SNUM add(SNUM left,SNUM right); //加法SNUM sub(SNUM left,SNUM right); //减法SNUM multiply(SNUM left,SNUM right); //乘法SNUM divide(SNUM left,SNUM right); //除法SNUM mod(SNUM left,SNUM right);//求摸运算函数的定义1 SNUM multiply(SNUM left,SNUM right){2//left作为被乘数,right作为乘数3 SNUM mul = (struct num*)malloc(sizeof(struct num));4int i,j;5for(i=0;i<LEN;i++){6 mul->number[i]=0;7 }89if(left->symbol==right->symbol){10 mul->symbol='+';11 }else{12 mul->symbol='-';13 }14151617for(i=0;i<right->len;i++){18for(j=0;j<left->len;j++){19 mul->number[i+j]+=left->number[j]*right->number[i];20 }21 }22232425////进位化简26int len = left->len+right->len-1; //长度2728//29for(i=0;i<len;i++){30 mul->number[i+1]+=mul->number[i]/10;31 mul->number[i]%=10;3233if(i==len-1){34if(mul->number[i+1]!=0){ //还存在⾼位35 len++;36 }else{ //进位完毕,退出37break;38 }39 }40 }4145for(i=len-1;i>=0;i--){46if(mul->number[i]==0){47 len--;48 }else{49break;50 }51 }52if(len==0){53 len=1;54 }5556 mul->len=len;5758free(left);59free(right);60return mul;61 }62636465//减⼀个数等于加上⼀个数的相反数66 SNUM sub(SNUM left,SNUM right){67 right->symbol=(right->symbol=='+'?'-':'+');68return add(left,right);69 }7071//⽐较两数绝对值⼤⼩72int compareAbs(SNUM left,SNUM right){73if(left->len>right->len){ //left的位数更多74return1;75 }else if(left->len<right->len){ //right的位数更多76return -1;77 }else{78int i=left->len-1;79while(i>=0){ //从⾼位开始⽐较80if(left->number[i]>right->number[i]){81return1;82 }83if(left->number[i]<right->number[i]){84return -1;85 }86 i--;87 }88return0; //两者绝对值相等89 }90 }919293 SNUM expToNum(char exp[]){9495 SNUM temp=(struct num*)malloc(sizeof(struct num)); 9697int locan=0;98//确定正负号99if(exp[0]=='+'||exp[0]=='-'){100 temp->symbol=exp[0];101 locan++;102 }else{103 temp->symbol='+';104 }105106//输⼊到数组107int count=0;108while(exp[locan]!='\0'){109 temp->number[count]=exp[locan]-'0';110 locan++;111 count++;112 }113114int i=count;115for(i=count;i<LEN-1;i++){116 temp->number[i]=0;117 }118119 temp->len=count;120121122//数组逆序从个位开始计算123 reverse(temp->number,temp->len);124125return temp;129void reverse(int a[],int len){130int i,temp;131for(i=0;i<len/2;i++){132 temp = a[i];133 a[i] = a[len-1-i];134 a[len-1-i] = temp;135 }136 }137138139140//元加法,假设left和right都为正数或0141 SNUM anti_add(SNUM left,SNUM right){142int i=0;143144while(i<left->len||i<right->len){145int sum=0;146 sum=left->number[i]+right->number[i]; 147if(sum>=10){148 left->number[i]=sum%10;149 left->number[i+1]+=sum/10; //进位150 }else{151 left->number[i]=sum; //不进位152 }153154 i++;155 }156157if(left->number[i]!=0){158 i+=1;159 }160161 left->len=i;162return left;163 }164165//实现正数或负数的加法166 SNUM add(SNUM left,SNUM right){167 SNUM temp;168if(left->symbol==right->symbol){169 temp = anti_add(left,right);170 }else{171if(compareAbs(left,right)>=0){172 temp = anti_sub(left,right);173174 }else{175 temp = anti_sub(right,left);176 }177 }178return temp;179 }180181//元减法,假设left>=right,left和right均为正数或0 182 SNUM anti_sub(SNUM left,SNUM right){183int i=0;184int count=0;185while(i<left->len){186int temp = left->number[i]-right->number[i]; 187if(temp<0){188 left->number[i+1]-=1;189 left->number[i]=temp+10; //退位190 }else{191 left->number[i]=temp;192 }193194 count+=1;195196 i++;197 }198199200201202//舍掉多余的0203for(i=count-1;i>=0;i--){204if(left->number[i]==0){205 count--;206 }else{207break;208 }213 }214215 left->len=count; 216return left;217218 }。
c语言算术运算符
c语言算术运算符c语言算术运算符在数学运算中最常见的就是加减乘除四则运算。
C语言中的算术运算符就是用来处理四则运算的符号,这是最简单、最常用的运算符号。
下面是店铺为你整理的c语言算术运算符相关介绍!下表是C语言中的算术运算符及其用法。
算术运算符看上去都比较简单,也很容易理解,但在实际使用时还有很多需要注意的问题,具体如下:1、进行四则混合运算时,运算顺序遵循数学中“先乘除后加减”的原则。
2、在进行自增(++)和自减(--)的运算时,如果运算符(++或--)放在操作数的前面则是先进行自增或自减运算,再进行其他运算。
反之,如果运算符放在操作数的后面则是先进行其他运算再进行自增或自减运算。
请仔细阅读下面的代码块,思考运行的结果。
int num1 = 1; int num2 = 2;int res = num1 + num2++;printf("num2=%d" + num2);printf("res=%d" + res);上面的代码块运行结果为:num2=3,res=3,具体分析如下:第一步:运算mum1+mun2++的结果,此时变量mun1,mum2的值不变。
第二步:将第一步的运算结果赋值给变量 res,此时 res值为 3。
第三步:mum2进行自增,此时其值为 3。
3、在进行除法运算时,当除数和被除数都为整数时,得到的结果也是一个整数。
如果除法运算有浮点数参与运算,系统会将整数数据隐形类型转换为浮点类型,最终得到的结果会是一个浮点数。
例如, 2510/1000 属于整数之间相除,会忽略小数部分,得到的结果是2,而2.5/10 的`实际结果为0.25。
请思考一下下面表达式的结果:3500/1000*1000所得结果为3000。
由于表达式的执行顺序是从左到右,所以先执行除法运算 3500/1000,得到结果为 3,然后再乘以 1000,最终得到的结果就是 3000。
四则运算表达式求值(栈+二叉树-c++版)
HUNAN UNIVERSITY 课程实习报告题目:四则运算表达式求值学生:周华毅学生学号:201308010411专业班级:计科1304 指导老师:吴帆完成日期:2015/5/1一、需求分析a)四则运算表达式求值,将四则运算表达式用中缀表达式表示,然后转换为后缀表达式,并计算结果。
b)本程序要求利用二叉树后序遍历来实现表达式的转换,同时可以使用实验2的结果来求解后缀表达式的值。
c)在字符界面上输入一个中缀表达式,回车表示结束。
如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
d)测试数据输入:21+23*〔12-6〕输出:21 23 12 6 -*+二、概要设计抽象数据类型为实现上述程序的功能,应以字符串存储用户的输入,以及计算出的结果。
算法的基本思想根据题目要求,利用二叉树后序遍历来实现表达式的转换。
该算法的基本模块包括二叉树的建立以及如何把输入的中缀表达式利用二叉树后序遍历转化为后缀表达式。
1、首先要将输入的中缀表达式〔数字字符〕存入到二叉树中,由于存在两位或者两位以上的数,甚至还有小数,所以考虑用字符型指针存储数字字符和操作符。
2、为了便于将中缀表达式存入二叉树中,在录入中缀表达式后,要进行相应的处理,比方去掉空格符,添加结束标志,如‘=’、‘#’等。
3、中缀表达式存入到二叉树的过程中,要注意处理的顺序,如‘+’、‘-’号的优先级比‘*’、‘/’号的低,当遇到‘*’、‘/’号时,要判断树以上的节点中是否有‘+’、‘-’号,有的话要与其交换位置。
遇到‘〔’时要反复创建二叉树的结点,构建子二叉树,考虑到括号内要处理的步骤可能会较多,可以考虑用递归。
遇到‘〕’时则直接结束此子二叉树的建立。
此外二叉树中叶子结点存储操作数,非叶子结点存储操作码。
4、对创建好的二叉树进行后序遍历,即可得到相应的后缀表达式,实现方法可以用递归的方式,由于后面还要计算表达式的值,故便利的过程中要将结点中得到的数据存入新的字符数组中。
c语言实现分数的四则运算
c语言实现分数的四则运算1. 前言分数,是我们初中数学学习的必修课程之一。
尽管在现实生活中或商业运营中,我们几乎不会用到分数的四则运算,但在计算机科学领域中,这个概念却显得尤为重要。
在这篇文章中,我们将会探究如何用C语言实现分数的四则运算,希望能对学习C语言和分数的学习者们有所帮助。
2. 定义分数结构体在C语言中,我们可以用结构体来定义一个分数类型。
一个分数包含两个整数:分子和分母。
因此,我们可以这样定义一个分数结构体:```cstruct fraction {int numerator; // 分子int denominator; // 分母};```3. 分数约分我们知道,约分是化简分数的一种基本方法,可以减少计算过程中分数的复杂性。
所以,在进行分数的四则运算之前,我们需要先将分数化简为最简形式。
例如,分数12/16可以化简为3/4,而分数6/9可以化简为2/3。
如何实现分数的约分呢?我们可以通过求出分子和分母的最大公约数(GCD),然后将它们同时除以这个最大公约数,从而得到最简形式的分数。
这样约分的好处在于能够节省内存和计算时间,同时也便于与其它化简后的分数进行比较。
下面是一个实现分数约分的函数:```cint gcd(int a, int b) { // 辗转相除法求最大公约数return (b == 0) ? a : gcd(b, a % b);}void reduce_fraction(struct fraction* f) {int g = gcd(f->numerator, f->denominator);f->numerator /= g;f->denominator /= g;}```该函数将传入的分数指针所指向的分数约去最简形式。
具体而言,我们先调用gcd函数求出分子和分母的最大公约数g,然后再将分子和分母都除以g,从而得到最简形式的分数。
4. 分数加减乘除有了分数约分函数后,我们便可以开始实现分数的四则运算。
C语言 大数四则运算
乘法运算的实现 首先说一下乘法计算的算法,从低位向高 位乘,在竖式计算中,我们是将乘数第一 位与被乘数的每一位相乘,记录结果,之 后,用第二位相乘,记录结果并且左移一 位,以此类推,直到计算完最后一位,再 将各项结果相加。得出最后结果。
计算的过程基本上和小学生列竖式做乘法相同。 为编程方便,并不急于处理进位,而将进位问题 留待最后统一处理。 ans[i+j] = a[i]*b[j];
for (i = M-1; (i >= 0)&&(num1[i] == 0); i --) ;//找到第一个不是 0的数的位置 if (i >= 0) //从高位到低位输出每个数 for (; i >= 0; i --) printf ("%d",num1[i]); else printf ("0\n"); }
大数除法
幂运算的实现
幂的实现是最为简单的了,国为有了前面 的算法做铺垫,就是调用乘法函数,来循 环去自乘,幂指数相应减1,直到幂指数变 为0时结束。
下标
0 1
1 6
2 6
3 4
4 4
5 3
6 4
7 3
8 1
9 8
加法运算的实现
+
加数
9
9
6
8
6
7
4
6
4
5
3
4
4
3
3
2
0
0
0
被加数 1
0
1、进位为1 初始化进位为0,各对应 6 2、进位为1 位相加后再加上进位数
5
3、进位为1
2
4、进位为1
由低位向高位相加计算,直至所有运算结束
四则运算表达式求值
HUNAN UNIVERSITY背景在工资管理软件中,不可避免的要用到公式的定义及求值等问题。
对于数学表达式的计算,虽然可以直接对表达式进行扫描并按照优先级逐步计算,但也可以将中缀表达式转换为逆波兰表达式,这样更容易处理。
问题描述四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。
一.需求分析(1)本程序利用二叉树后序遍历来实现表达式的转换,同时可以使用栈来求解后缀表达式的值。
(2)输入输出的格式:输入:在字符界面上输入一个中缀表达式,回车表示结束。
输出:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式和计算结果,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
(3)测试用例:输入:21+23*(12-6)+9输出:21 23 12 6 -*+ 9+result is 168二.概要设计(1)抽象数据类型:由于四则运算表达式中运算符可能有多个后继,而运算的对象无后继,可以采用二叉树来实现把中缀表达式转换为后缀表达式。
数据对象:四则运算符及整数数据关系:运算符有多个后继,二运算对象的值无后继基本操作:后序遍历,二叉树的构建和摧毁,插入,删除经过二叉树的后序遍历后的表达式惊醒运算是满足后进先出的原则,采用栈来实现四则运算表达式的求值。
数据对象:运算符(字符)及整数数据关系:后进先出基本操作:入栈,出栈,栈的构建和删除(2)算法基本思想:用二叉树来存储四则表达式,再通过后序遍历把中缀表达式转换为后缀表达式,最后通过栈来计算表达式的值,最后输出后序表达式和表达式的值。
(3)程序的流程:该程序有三个模块组成:1.输入模块:输入一个中缀表达式2.处理模块:把中缀表达式转换为后缀表达式3.计算模块:计算表达式的值4.输出模块:输出后缀表达式及表达式的值三.详细设计(1)物理数据类型:采用指针来实现二叉树,其中分支节点存储运算符,用叶子节点存储操作数,可以减少二叉树的结构性开销。
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 - * +"。
第三步:求解后缀表达式在将表达式转换为后缀表达式之后,我们可以使用栈来求解后缀表达式。
c语言表达式运算 -回复
c语言表达式运算-回复C语言表达式运算表达式是编程语言中非常重要的概念之一。
它可让我们在程序中对数据进行各种操作,从而实现我们的算法目标。
在C语言中,表达式由操作数和操作符组成。
操作数可以是常量、变量、函数返回值或其他表达式。
而操作符则用来执行特定的操作,例如算术运算、逻辑运算、赋值运算等等。
本文将深入探讨C语言中的表达式运算,从最基本的算术运算到更高级的逻辑运算,以视觉化和易懂的方式,逐步回答您关于表达式运算的问题。
一、算术运算算术运算主要包括加法、减法、乘法和除法四种基本运算。
在C语言中,可以使用加号(+)、减号(-)、乘号(*)和除号(/)执行这些运算。
1.1 加法运算加法运算用于将两个操作数相加,得到和。
例如:int a = 5;int b = 3;int c = a + b;在这个例子中,变量a和b分别赋值为5和3,然后将它们相加,结果赋给变量c。
最后,c的值将是8。
1.2 减法运算减法运算用于将第一个操作数减去第二个操作数,得到差。
例如:int a = 5;int b = 3;int c = a - b;在这个例子中,变量a和b分别赋值为5和3,然后将b从a中减去,结果赋给变量c。
最后,c的值将是2。
1.3 乘法运算乘法运算用于将两个操作数相乘,得到积。
例如:int a = 5;int b = 3;int c = a * b;在这个例子中,变量a和b分别赋值为5和3,然后将它们相乘,结果赋给变量c。
最后,c的值将是15。
1.4 除法运算除法运算用于将第一个操作数除以第二个操作数,得到商。
例如:int a = 5;int b = 3;int c = a / b;在这个例子中,变量a和b分别赋值为5和3,然后将a除以b,结果赋给变量c。
最后,c的值将是1。
需要注意的是,除法运算结果可能不是一个整数,而是一个浮点数。
如果想保留小数部分,可以使用浮点数类型来声明变量。
二、逻辑运算逻辑运算用于执行条件判断,通常用于if语句、循环语句等控制流程结构中。
四则运算表达式计算前序遍历
四则运算表达式计算前序遍历摘要:一、前序遍历的定义与意义二、四则运算表达式计算的基本方法三、使用前序遍历解决四则运算表达式计算问题四、前序遍历在实际应用中的优势与局限五、总结正文:一、前序遍历的定义与意义前序遍历是一种二叉树遍历方式,也被称为先序遍历。
它遵循“根- 左-右”的顺序访问二叉树的节点。
在计算机科学中,前序遍历常用于表达式的计算,特别是四则运算表达式的计算。
通过对四则运算表达式进行前序遍历,可以轻松地实现表达式的求值。
二、四则运算表达式计算的基本方法四则运算表达式计算主要包括以下几个步骤:1.解析表达式:将表达式字符串转换为抽象语法树(AST)。
2.评估优先级:根据运算符的优先级,对AST 中的节点进行排序。
3.计算表达式:按照前序遍历的顺序,对AST 中的节点进行计算,得出最终结果。
三、使用前序遍历解决四则运算表达式计算问题前序遍历在四则运算表达式计算中的优势在于,它能够确保每个节点在计算过程中只被访问一次,避免了重复计算。
同时,前序遍历的顺序遵循了运算符的优先级,使得计算过程更加清晰易懂。
四、前序遍历在实际应用中的优势与局限前序遍历在四则运算表达式计算中的优势已经在上一个部分中提到。
然而,它也有一定的局限性。
例如,当表达式中存在括号时,前序遍历可能无法正确计算表达式的值。
在这种情况下,需要使用其他遍历方式,如中序遍历或后序遍历,来解决这个问题。
五、总结总的来说,前序遍历在四则运算表达式计算中起到了关键作用。
它不仅使得计算过程更加高效,还有助于理解表达式的内在逻辑。
利用四则运算计算算式的值
利用四则运算计算算式的值数学作为一门基础学科,对于中学生来说是必修课程之一。
而四则运算作为数学的基础,是学习其他数学知识的基石。
掌握了四则运算,我们就能够解决各种实际问题,进行更复杂的数学运算。
今天,我将为大家介绍如何利用四则运算计算算式的值。
首先,我们来看一个简单的例子:计算5 + 3。
这个算式中,+ 是加法运算符,5 和3 是运算数。
我们只需要按照运算符的规则,将两个运算数相加,得到结果8。
这个例子展示了加法运算的基本原理。
接下来,我们来看一个稍微复杂一点的例子:计算12 - 7。
这个算式中,- 是减法运算符,12 和 7 是运算数。
同样地,我们按照运算符的规则,将两个运算数相减,得到结果 5。
这个例子展示了减法运算的基本原理。
除了加法和减法,我们还有乘法和除法这两种运算。
乘法运算使用 * 运算符,除法运算使用 / 运算符。
举个例子,计算8 * 4,我们将两个运算数相乘,得到结果 32。
同样地,计算12 / 3,我们将被除数 12 除以除数 3,得到结果 4。
这两个例子展示了乘法和除法运算的基本原理。
在实际计算中,我们常常会遇到多个运算符的算式。
这时,我们需要按照一定的规则来确定运算的顺序。
这个规则被称为运算优先级。
一般来说,乘法和除法的优先级高于加法和减法。
举个例子,计算 3 + 4 * 2,我们先计算乘法 4 * 2 得到 8,再进行加法 3 + 8,最终得到结果 11。
如果不按照运算优先级进行计算,而是从左到右依次计算,结果将会不同。
除了运算优先级,我们还需要注意括号的运用。
括号可以改变运算的顺序,使得我们能够先计算括号内的算式。
举个例子,计算 (3 + 4) * 2,我们先计算括号内的加法 3 + 4 得到 7,再进行乘法 7 * 2,最终得到结果 14。
括号的运用可以帮助我们清晰地表达算式的意思,避免产生歧义。
除了基本的四则运算,我们还可以通过运算符的组合来进行更复杂的运算。
例如,计算 2 + 3 * 4 - 5 / 2,我们按照运算优先级和括号的规则,先计算乘法 3 * 4 得到 12,再进行除法 5 / 2 得到 2.5,最后进行加法和减法,得到结果 14.5。
四则运算解析及计算
四则运算解析及计算四则运算是中缀表达式,需要将其转化为后缀表达式。
原因是计算中缀表达式很困难。
明确运算符的优先级:优先级(数字越⼤,优先级越⾼)运算符2+-1*/0()格式化四则表达式输⼊的表达式可能出现⽆⽤的字符,需要去除否则影响下⾯的判断逻辑。
处理⽅法为,遍历整个字符串,删除换⾏、空格和制表符。
后缀表达式转化中缀表达式转化为后缀表达式的基本步骤如下:1.初始化⼀个运算符栈。
2.从输⼊的表达式的字符串中依次从左向右每次读取⼀个字符。
3.如果当前读取的字符是操作数,则直接填写到后缀表达式中 (如果后缀表达式末尾已经有操作数,需要使⽤逗号分隔开)。
4.如果当前字符是“(”左括号,将其压⼊运算符栈。
5.如果当前字符为运算符,则分三种情况:(1)当前运算符栈为空,将其压⼊运算符栈。
(2)当前运算符的优先级⼤于栈顶元素,则将此运算符压⼊运算符栈;否则,弹出栈顶的运算符到后缀表达式,反复弹出,直到该运算符优先级⼤于栈顶元素或者栈为空时,然后将当前运算符压栈。
回到步骤2继续读取。
(3)如果上⼀次读到的也是运算符,则中缀表达式错误直接返回6.如果当前字符是“)”右括号,反复将栈顶元素弹出到后缀表达式,直到栈顶元素是左括号“(”为⽌,并将左括号从栈中弹出丢弃。
如果找不到“(”则中缀表达式错误直接返回7.如果读取还未完成,回到步骤2.8.如果读取完成,则将栈中剩余的运算符依次弹出到后缀表达式。
※如果表达式中出现负数或者⼩数,需对负数和⼩数点采取特殊处理:(1)如果是负数,需要把“-”⼀起存放到后缀表达式中同时还要添加⼀个特殊字符“!”⽤于标记负数。
两种情况下出现“-”可判定为负数。
A.“-”为⾸字符且下⼀个字符为数字;B.“-”为⾮⾸字符且位于“(”之后且后⼀个字符为数字;(2)如果有⼩数,需要记录⼩数点的位数举例:输⼊的四则表达式是 -15. *((-5+.6)*87-(-4.592+3.33)*8)处理后的后缀表达式为:!-15.,!-5,.6,+87,*!-4.592,3.33,+8,*-*后缀表达式求值:从左到右读取1、设置⼀个栈,开始时,栈为空;2、然后从左到右读取后缀表达式,若遇操作数,则进栈;3、若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕;4、最后,栈中仅有⼀个元素,即为运算的结果。
湖南大学数据结构试验3四则运算表达式求值
实验四四则运算表达式的求值一、需求分析1. 要求对四则运算表达式求值,将四则运算表达式用中缀表达式表示,然后转换为后缀表达式,并计算结果。
利用二叉树来实现要求,注意浮点数和整形数的转换。
利用二叉树后续遍历来实现表达式的转换,同时可以使用实验2的结果来求解后缀表达式的值。
2.中缀表达式由键盘输入(输入的字符串长度小于100),对非法表达式做错误判断和说明在Dos界面输出出列的项3.测试数据输入:21+23*(12-6)输出:21 23 12 6 -*+result is 159.00二、概要设计1.输入中缀表达式转换后缀表达式,以及计算出的结果ADT LinkList {数据对象:D是具有相同特性的数据元素的集合。
数据关系:若D为空寂,则称为空树;(1).若D仅含有一个数据元素,则R为空集,否则R={H},H是如下二元关系:在D中仅存在为一的称为根的数据元素root,它在关系H下无前驱;(2).若D-{root}的一个划分D1,D2,…Dm(m>0),对任意j不等于k(1<=j,k<=m)有Dj和Dk的交集为空,且任意的i(1<=i<=m),唯一存在数据元素Xi属于Di,有<root,Xi>属于H;(3).对应于D-{root}的划分,H-{<root,Xi>,…,<root,Xm>}有唯一的一个划分H1,H2,…Hm(m>0),对任意j不等于k(1<=j,k<=m)有Hj和Hk的交集为空,且对任意i(1<=i<=m),Hi是Di上的二元关系,(Di,{Hi})是一棵符合定义的树,称为根root的子树。
基本操作:int CrtNode(stack <BiTree> &PTR, char *c)操作结果:创建二叉树的根节点,并把值保存在根节点。
void CrtSubTree(stack <BiTree> &PTR, char c)初始条件:二叉树根节点存在操作结果:建立二叉树的子树void CrtExptree(BiTree &T, char exp[])初始条件:二叉树存在操作结果:根据字符串exp的内容构建表达式树Tvoid PostOrderTraverse(BiTree &T, char * exp ,int &count)初始条件:二叉树不为空操作结果:后序遍历二叉树,依据T->len的值,把T->data中的字符依次添加到当前exp字符串的尾端} ADT LinkList2.本程序包含三个基本模块(1)主程序模块:其中又包括构建二叉树和后序遍历二叉树及计算后序表达式的值(2)线性表模块:实现线性表的抽象数据类型(3)元素结构单元模块:定义线性表每个元素的结构三、详细设计1.元素类型,二叉树类型typedef struct BiTNode {TElemType data;int len; //data字符串中字符的个数struct BiTNode * lchild, * rchild;}BiTNode, *BiTree;栈类型:c++标准容器stack容器2.根据二叉树和栈的特点,T即为该二叉树的名称,该程序的基本操作具体实二叉树T—>后序遍历二叉树—>计算二叉树的后序表达式的值—>删除中间指针—>结束3.主程序中:四、调试分析1.输入“4**”诸如此类的表达式时,程序运行时不会报出错误,因为该程序不能判别一些不合法公式的输入情况,类似的情况太多,着重点不在这些错误上。
四则运算表达式求值
HUNAN UNIVERSITY数据结构实验报告题目:四则运算表达式学生姓名梁天学生学号************专业班级计科1403指导老师李晓鸿日期2016.04.30背景在工资管理软件中,不可避免的要用到公式的定义及求值等问题。
对于数学表达式的计算,虽然可以直接对表达式进行扫描并按照优先级逐步计算,但也可以将中缀表达式转换为逆波兰表达式,这样更容易处理。
问题描述四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。
基本要求(1)本程序是利用二叉树后序遍历来实现表达式的转换,同时可以使用实验二的结果来求解后缀表达式的值。
(2)输入输出格式:输入格式:在字符界面上输入一个中缀表达式,回车表示结束。
请输入表达式:输入一个中缀表达式输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
逆波兰表达式为:输出逆波兰表达式运算结果为:输出运算后的结果输入输出格式测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+一、需求分析本实验是求解四则运算的问题,通过对四则运算式的输入,可以知道运算式的运算先后顺序和表达式的结果。
四则运算中的运算有优先级的问题,如何更快速方便地解决这个问题,我们可以考虑将中缀表达式(即要求运算的表达式)转换为后缀表达式(不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,这样可以更方便地用计算机计算出结果。
转换为后缀表达式后输出后缀表达式,计算并输出结果。
二、概要设计抽象数据类型1.为了更方便地用计算机处理优先级的问题,所以把中缀表达式转换为后缀表达式来计算,而由中缀表达式转换为后缀表达式可以用二叉树来实现,因为如果二叉树的中序遍历为四则表达式时,后序遍历的结果就是后缀表达式了,所以我们可以设计一个二叉树来存表达式。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
作者:韦延昭 Email: yls8420@
26,April 26, 2008
引言:四则运算表达式包含操作数、操作符以及括号等。操作数
可以是任意实数,操作符包括加( + )、减(- )、乘(* )以及 除( / )等。本文将利用 C++标准模板库(STL)中的堆栈和队列 来编程实现计算任意实数的四则运算表达式的值。
问题:设计一个处理和计算四则表达式的类,该类有一个字符串
类型的成员变量用来表示初始的中缀表达式的字符串,例如中缀表达 式:
(2.99-4.32)*(90.8-78.66)+78.0/3.14 通过该类的成员函数将该表达式的值计算出来。 要求:操作数可以是任意实数、括号对数以及表达式长度没有限 制。
分析:由于操作数是任意的实数,所以必须将原始的中缀表达式
que.push(str); } else { if(str.size() != 0)
que.push(str); str = ch; que.push(str);
str = ""; } }
return que; }
6)ChangeToSuffix()函数。将保存在队列中的中缀表达式转换为后 缀表达式,并保存在栈中。这个函数也是整个表达式算法的关键,这 里需要两个栈 stack_A 和 stack_B,分别在转换过程中临时存放后 缀表达式的操作数与操作符。依次从中缀表达式队列 que 中出列一 个元素,并保存在一个 string 变量 str 中,然后按以下几方面进行 处理: ①如果 str 是“(”,则将 str 推入栈 stack_B。 ②如果 str 是“)”,则要考虑 stack_B 的栈顶是不是“(”,是的话就 将“(”出栈 stack_B;如果不是,则将 stack_B 出栈一个元素(操 作符),然后将其推入栈 stack_A。 ③如果 str 是“+”或“-”,则要考虑有括号和优先级的情况,如果 栈 stack_B 为空或者栈顶为“(”,则将 str 推入栈 stack_B;因为操 作符“+”和“-”优先级相同(谁先出现就先处理谁进栈 stack_A), 并且低于“*”和“/”,所以当栈 stack_B 不为空并且栈顶不为“(”, 则依次循环取出 stack_B 的栈顶元素并依次推入栈 stack_A,循环 结束后再将 str 推入栈 stack_B。 ④如果 str 是“*”或“/”,因为它们的优先级相同并且高于“+”和 “-”,所以如果栈 stack_B 为空或者栈顶为“+”、“-”或“(”就直 接将 str 推入栈 stack_B;否则就将 stack_B 弹出一个元素并将其
的字符串。
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 类型的值。其功能是计算转换后 的后缀表达式的值,即原始中缀表达式的值。
ch = m_string.at(i); switch(ch) { case '(': stack.push(ch);
break; case ')': if(stack.empty())
return false; else stack.pop(); break; default:break; } } return stack.empty(); }
queue<string> que;
if(!IsWellForm())// 括号是否匹配 { cout<<"The original expression is not well-form. Please check it and try
again!"<<endl; return que; }
string str = "";
5)DivideExpressionToItem()函数。分解出原始中缀表达式中的操
作数、操作符以及括号,保存在队列中,分解完成后队列中的保存顺
序如下图所示:
图 1 分解表达式
其 算 法 思想 是: 从左 往 右按 一个字 节 依次 扫描 原 始中缀表达式
m_string,碰到连续的数字或小数点就加到 string 变量 str 中;如
bNumber = true; break; case '(': case ')': case '+': case '-': case '*': case '/': bNumber = false; break; default:continue; }
if(bNumber) { str += ch; if(i==size-1)
类 ExpressionType 的定义包含了三个头文件<string>、<stack>
以及<queue>,这是标准模板库里现成的东西,直接拿来用就行了,
不必再自己写 栈和队列, 它们都 在 std 命名空间里 。 下面对类
ExpressionType 的成员作介绍:
u m_string: 私有成员变量,字符串类型。主要用于存储表示原始中缀表达式
法在类中实现。首先设计一个类 ExpressionType,其具体定义如下:
/**************************************************************************************** * ExpressionType.h ****************************************************************************************/ #include <string> #include <stack> #include <queue> using namespace std;
果碰到括号或操作符就将原先的 str 推入队列,然后将括号或操作符
赋予 str,再将 str 推入队列,并将 str 赋予空值,依次循环进行直
到扫描 m_string 完成。其具体实现代码如下:
queue<string> ExpressionType::DivideExpressionToItem() {
中的操作数、操作符以及括号分解出来,并以字符串的形式保存;然 后再将其转换为后缀表达式的顺序,为什么要转换为后缀表达式的形
式呢?原因是后缀表达式可以很容易地利用堆栈计算出表达式的值。 例如有如下的中缀表达式:
a+b-c 转换成后缀表达式为:
ab+c然后分别按从左到右放入栈中,如果碰到操作符就从栈中弹出两个操 作数进行运算,最后再将运算结果放入栈中,依次进行直到表达式结 束。如上述的后缀表达式先将 a 和 b 放入栈中,然后碰到操作符“+”, 则从栈中弹出 a 和 b 进行 a+b 的运算,并将其结果 d(假设为 d) 放入栈中,然后再将 c 放入栈中,最后是操作符“-”,所以再弹出 d 和 c 进行 d-c 运算,并将其结果再次放入栈中,此时表达式结束,则 栈中的元素值就是该表达式最后的运算结果。当然将原始的中缀表达 式转换为后缀表达式比较关键,要同时考虑操作符的优先级以及对有 括号的情况下的处理,相关内容会在算法具体实现中详细讨论。
推入栈 stack_A 中,然后再将 str 推入栈 stack_B 中。 ⑤除了上述情况 外就只剩下操作数 了,操作数 就可以 直接推 入栈 stack_A 中。注意整个过程中栈 stack_B 中的元素只能是如下几种: “(”、“+”、“-”、“*”、“/”,而最终栈 stack_A 保存的是后缀表达式, 只有操作数和操作符,如下图所示:
4)IsWellForm()函数。判断原始中缀表达式的括号是否匹配,可以
利用栈简单实现,即遇到“(”进栈,遇到“)”就从栈中弹出一个元
素,直到表达式结束。如果栈为空则表示括号匹配,否则不匹配。算
法实现如下:
bool ExpressionType::IsWellForm() { stack<char> stack; int size = Size(); char ch; for(int i = 0; i < size; i++) {