首页 C语言 后缀表达式计算

C语言 后缀表达式计算

举报
开通vip

C语言 后缀表达式计算如有侵权,请联系网站删除,仅供学习与交流【精品文档】第PAGE12页C语言后缀表达式计算一、设计思想计算算数表达式并求值,采取的共有两种方法:先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。对算数表达式进行直接的计算。第一种算法这种解决方案又分为两步:1.将表达式先转化为后缀表达式的字符串数组2.利用后缀表达式进行计算在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加...

C语言 后缀表达式计算
如有侵权,请联系网站删除,仅供学习与交流【精品文档】第PAGE12页C语言后缀 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 达式计算一、设计思想计算算数表达式并求值,采取的共有两种方法:先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。对算数表达式进行直接的计算。第一种算法这种解决 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 又分为两步:1.将表达式先转化为后缀表达式的字符串数组2.利用后缀表达式进行计算在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。数组中存的就是后缀表达式。得到后缀表达式后,进行计算,要用到数值栈。首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。第二种算发首先要建立两个栈,一个用来存放操作符,一个用来存放数值。开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。扫描结束后,计算也结束了,计算的结果就存放在数值栈中,最后把数值栈中的数取出,就是所得的计算结果。容错的算法简要:括号匹配:当扫描到左括号是,左括号直接入栈,扫描到右括号时,则左括号出栈,如果栈为空,则右括号多,如果最后栈中还有括号,则左括号多。给出错误提示。除数不为0:当扫描到'/'时,就判断其后面的数字是否为0,如果为0报错。取余运算:取余运算时,操作数判断是否为整数,不为整数报错。二、算法流程图第一种算法:先将表达式转化为后缀表达式,然后计算其主函数流程图为:得到用户输入的中缀表达式调用容错函数存在错误报错并结束无错调用函数得到后缀表达式后缀表达式的计算返回计算结果调用直接计算的函数返回直接计算的结果图1主函数算法流程图其中将中缀表达式转化为后缀表达式的主要流程为:取得字符并判断如果是数字或小数点直接放入字符数组中在其后加入分隔符如果是操作符与栈顶比较判断哪类括号直接入栈右括号取出不为'('从栈中取出操作符放入数组直接入栈优先级高于栈顶如果是括号出栈存入数组中左括号优先级不高于栈顶图2中缀转化为后缀算法流程图后缀表达式的计算,实现的流程图为:从数栈取2个数做相应计算结果存入数栈判断符号类型得到后缀表达式数字字符操作符转化为浮点数入栈从数栈中取出计算结果作为返回值图3后缀表达式计算算法流程图下面介绍直接计算出结果的算法的实现:栈非空栈空低于栈顶高于栈顶NOYES左括号得到中缀表达式从字符串中取出一个字符判断字符类型数字字符操作符转化为浮点数入栈括号括号类型直接入栈右括号从栈中取出操作符是否为(丢弃(放入数组与栈顶比较直接入栈取出栈顶两个数作相应计算结果存入数栈符号栈是否为空将数值栈顶返回取栈顶符号与2个数计算,结果存入数值栈图4直接计算中缀表达式算法流程图三、源代码下面给出的是用先转后缀再计算和直接计算的算法实现的程序的源代码:#include/*导入需要用到的各种包*/#include#includetypedefstruct/*定义结构体用来存储操作符*/charop;/*存储字符*/intlevel;/*存储优先级*/}OpNode;typedefstructOpNodeop[100];inttop;intsize;/*表示栈内元素的个数*/}stack;/*定义符号栈*/voidinit(stack*st)/*初始化栈*/st->size=0;st->top=0;OpNodepop(stack*a)/*出栈*/if(a->size==0)/*如果栈为空结束操作*/exit(-1);a->size--;returna->op[--(a->top)];/*取出栈顶元素*/voidpush(stack*a,OpNodeop)/*入栈函数*/a->size++;a->op[(a->top)++]=op;OpNodetop(stack*a)/*观察栈顶函数*/if(a->size==0)/*如果栈为空结束操作*/printf("stackisempty\n");exit(-1);returna->op[(a->top)-1];/*只得到栈顶的值而不出栈*/typedefstruct/*定义数值栈*/doublenum[100];inttop;/*栈顶指针*/intsize;}numstack;voidinit2(numstack*st)/*初始化数值栈*/st->size=0;st->top=0;doublepop2(numstack*a)/*数值栈出栈*/if(a->size==0)/*出栈前的判空*/exit(-1);a->size--;returna->num[--(a->top)];/*得到栈顶的值*/voidpush2(numstack*a,doublenum)/*入栈*/a->size++;a->num[(a->top)++]=num;voidmain()/*主函数*/voidchange(charstr[],charexp[]);/*声明要用到的各个函数*/doubleCalResult(charexp[]);/*声明后缀表达式的计算函数*/doubleDirectcalresult(charstr[]);intcheck(charstr[],charchestr[100]);charstr[100],exp[100],chestr[100];/*str存储原算术表达式,exp存储对应的printf("算术表达式为:\n");后缀表达式,chestr存储容错字符'^'*/gets(str);if(check(str,chestr))/*调用容错函数*/{printf("表达式错在:\n");printf("%s\n",str);printf(chestr);/*根据输入情况指出错误的地方*/exit(-1);change(str,exp);/*调用函数将中缀转化为后缀*/printf("后缀表达式为:%s\n",exp);printf("运算结果为:%f\n",CalResult(exp));/*调用函数计算后缀表达式*/printf("直接运算的结果为:%f\n",Directcalresult(str));/*调用直接计算函数*/voidchange(charstr[],charch[])/*将前缀表达式转化为后缀表达式*/inti=0;/*str的索引*/intk=0;charc;/*字符串中取出的放在C中*/stackst;/*定义符号栈*/OpNodeop;OpNodeops;init(&st);/*初始化符号栈*/c=str[i++];while(c!='\0')/*对字符串进行扫描*/if((c>='0'&&c<='9')||c=='.')/*如果字符为数字或小数点*/while((c>='0'&&c<='9')||c=='.')ch[k++]=c;/*将字符直接放入数组中*/c=str[i++];ch[k++]='|';/*在其后面放入一个分隔符*/if(c=='(')/*如果字符是左括号*/op.op='(';op.level=-1;/*定义其优先级为-1*/push(&st,op);/*将左括号直接入栈*/if(c==')')/*如果字符为右括号*/op=top(&st);/*首先观察栈顶*/while(st.size!=0&&op.op!='(')/*如果不是左括号并且栈不为空*/op=pop(&st);/*出栈并存入数组中*/ch[k++]=op.op;if(st.size>0)/*再次检查栈是否为空,*/op=top(&st);elsebreak;/*为空就结束*/pop(&st);/*去掉左括号*/if(c=='+'||c=='-')/*如果是+-号*/op.op=c;op.level=1;/*优先级为1*/if(st.size==0)push(&st,op);/*如果此时栈为空直接入栈*/elseops=top(&st);/*观察栈顶*/while(ops.level>=op.level)/*如果栈顶优先级高*/ops=pop(&st);ch[k++]=ops.op;/*将栈顶元素取出存入数组中*/if(st.size>0)ops=top(&st);/*进行判空操作,栈为空结束*/elsebreak;push(&st,op);/*此时栈顶优先级低,入栈*/if(c=='*'||c=='/'||c=='%')/*如果是*/进行*/op.op=c;op.level=2;/*优先级为1*/if(st.size==0)push(&st,op);/*如果此时栈为空直接入栈*/elseops=top(&st);/*观察栈顶*/while(ops.level>=op.level)/*如果栈顶优先级高*/ops=pop(&st);/*将栈顶元素取出存入数组中*/ch[k++]=ops.op;if(st.size>0)ops=top(&st);/*进行判空操作,栈为空结束*/elsebreak;push(&st,op);/*此时栈顶优先级低,入栈*/c=str[i++];/*索引自加检索下一个字符*/while(st.size!=0)/*最后判断栈如果不为空*/ops=pop(&st);/*取出栈内元素存入数组中*/ch[k++]=ops.op;ch[k]='\0';/*将\0作为结尾存入数组*/doubleCalResult(charexp[])/*后缀表达式的计算*/charc;numstacknumst;/*建立数值栈*/doubled1,d2,dr;intk=0;/*后缀表达式的索引*/inti=0;/*将字符转化为浮点数的索引*/char*s;chartrans[100];/*存字符表示的一段数字*/init2(&numst);/*实现数值栈*/c=exp[k++];while(c!='\0')/*开始扫描后缀表达式*/if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%')/*如果是操作符*/switch(c)case'+':/*如果是加法操作*/d2=pop2(&numst);d1=pop2(&numst);dr=d1+d2;/*相加后入栈*/push2(&numst,dr);break;case'-':/*如果是减法操作*/d2=pop2(&numst);d1=pop2(&numst);dr=d1-d2;/*相减后入栈*/push2(&numst,dr);break;case'*':/*如果是乘法操作*/d2=pop2(&numst);d1=pop2(&numst);dr=d1*d2;/*相乘后入栈*/push2(&numst,dr);break;case'/':/*如果是除法操作*/d2=pop2(&numst);d1=pop2(&numst);dr=d1/d2;/*相除后入栈*/push2(&numst,dr);break;case'%':/*如果是取余操作*/d2=pop2(&numst);d1=pop2(&numst);dr=(double)((int)d1%(int)d2);/*类型转化并取余后入栈*/push2(&numst,dr);break;if(c>='0'&&c<='9'||c=='.')/*如果是字符表示的数字*/while(c>='0'&&c<='9'||c=='.')trans[i++]=c;/*将字符存入数组进行下一个的扫描*/c=exp[k++];trans[i++]='\0';/*将表示数字的字符串结束*/i=0;s=trans;/*将指针指向该数组*/d1=atof(s);/*利用函数将字符串转化为浮点数*/push2(&numst,d1);c=exp[k++];returnpop2(&numst);/*最后结果将在数值栈中,取出作为返回值*/doubleDirectcalresult(charstr[])/*表达式的直接计算出结果*/stackms;/*建立符号栈*/numstackmns;/*建立数值栈*/doublecalculate(doubleod1,doubleod2,OpNodeop);intindex=0;/*str的索引*/intlen=strlen(str);charc;chartrans[100];/*存放数值的一段字符*/inti=0;/*trans的索引*/char*s;doubled;OpNodetempn;/*存放当前扫描的操作符*/OpNodetempln;doubleoda,odb,odr;doubleresult;/*作为返回值返回结果*/init(&ms);/*实现两个栈*/init2(&mns);while(index='0'&&c<='9'||c=='.')/*如果是数字字符或小数点*/while(c>='0'&&c<='9'||c=='.')trans[i++]=c;/*将其存入数组扫描下一个*/c=str[index++];trans[i++]='\0';/*扫描完一个数结束数组*/i=0;/*索引归0*/s=trans;d=atof(s);push2(&mns,d);/*转化为浮点数入栈*/if(c=='+'||c=='-')/*如果是+-*/tempn.level=1;/*优先级设为1*/tempn.op=c;if(ms.size==0)push(&ms,tempn);/*栈为空直接入栈*/elsetempln=top(&ms);while(templn.level>=tempn.level)/*栈顶优先级高*/templn=pop(&ms);/*取出操作数和操作符计算*/odb=pop2(&mns);oda=pop2(&mns);odr=calculate(oda,odb,templn);push2(&mns,odr);/*结算结果入栈*/if(ms.size>0)templn=top(&ms);/*如果栈空结束*/elsebreak;push(&ms,tempn);/*操作符入栈*/if(c=='*'||c=='/'||c=='%')/*如果是*/%操作*/tempn.level=2;/*定义优先级为2*/tempn.op=c;if(ms.size==0)push(&ms,tempn);/*栈空直接入栈*/elsetempln=top(&ms);while(templn.level>=tempn.level)/*栈顶优先级高*/templn=pop(&ms);/*取出操作数和操作符计算*/odb=pop2(&mns);oda=pop2(&mns);odr=calculate(oda,odb,templn);push2(&mns,odr);/*结算结果入栈*/if(ms.size>0)templn=top(&ms);elsebreak;/*如果栈空结束*/templn=top(&ms);push(&ms,tempn);/*操作符入栈*/if(c=='(')/*如果是左括号*/tempn.level=-1;tempn.op=c;/*直接入栈优先级定位-1*/push(&ms,tempn);if(c==')')/*如果是右括号*/while(tempn.op!='(')/*遇到左括号结束*/templn=pop(&ms);odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/oda=pop2(&mns);odr=calculate(oda,odb,templn);/*计算出结果入栈*/push2(&mns,odr);if(ms.size>0)tempn=top(&ms);elsebreak;/*如果栈空结束*/pop(&ms);/*取出左括号*/tempn=top(&ms);while(1)templn=pop(&ms);odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/oda=pop2(&mns);odr=calculate(oda,odb,templn);/*计算出结果入栈*/push2(&mns,odr);if(ms.size>0)tempn=top(&ms);/*如果栈空结束*/elsebreak;result=pop2(&mns);/*最后的结果在数值栈中返回*/returnresult;doublecalculate(doubleod1,doubleod2,OpNodeop)/*已知操作符和操作数的计算*/switch(op.op)case'+':returnod1+od2;case'-':returnod1-od2;/*判断操作符是哪个执行相应计算*/case'*':returnod1*od2;case'/':returnod1/od2;case'%':return(double)((int)od1%(int)od2);return0;/*如果上面的都没有执行返回0*/intcheck(charstr[],charchestr[100])/*容错函数*/charc;charcdivide;inti=0;/*str的索引*/stackche;/*括号匹配用到的栈*/OpNodetemp;intk=0;/*chestr的索引*/intisinteger(charinteger[100]);/*%计算是判断是否是整数*/chars1[10];/*%操作时存储%左右的数字*/chars2[10];intindexs1=0;/*s1s2的索引*/intindexs2=0;init(&che);intflag=0;/*0——没有出错1——有错*/inttag=0;c=str[i];/*开始扫描*/intj;/*数组chestr索引*/for(j=0;j<99;j++)chestr[j]='';/*数组初始化待以后加入'^'*/chestr[j]='\0';while(c!='\0')if(c=='(')/*如果是左括号就入栈*/temp.op=c;push(&che,temp);if(c==')')/*如果是右括号*/if(che.size>0)pop(&che);/*栈不为空就取出一个左括号*/elseflag=1;printf("缺少左括号\n");/*否则提示有错*/chestr[i]='^';/*右括号下加'^'*/if(c=='/')/*判断除数是否为0*/j=0;cdivide=str[i+1+j];/*取出除号后的数*/while(cdivide>='0'&&cdivide<='9'||cdivide=='.')/*如果是数或小数点就一直存*/s1[j++]=cdivide;if(cdivide!='0'&&cdivide!='.')/*如果不是0则正确并结束*/tag=1;break;cdivide=str[i+j+1];if(!tag)/*如果tag为0则存在错误除数为0*/chestr[i+1]='^';flag=1;/*flag为1表示有错*/if(c=='%')/*取余操作的容错*/while(str[i-indexs1-1]>='0'&&str[i-indexs1-1]<='9'||str[i-indexs1-1]=='.')/*以%为中心向前扫描*/s1[indexs1++]=str[i-indexs1-1];/*如果是数或小数点*/}/*放在s1中*/while(str[i+indexs2+1]>='0'&&str[i+indexs2+1]<='9'/*以%为中心向后扫描*/||str[i+indexs2+1]=='.'){/*如果是数或小数点*/s2[indexs2++]=str[i+indexs2+1];/*放在s1中*/if(isinteger(s1))/*调用函数判断s1内存到是否是整数*/printf("取余算法第一个数应为整数运算\n");flag=1;/*记录为有错*/chestr[i-indexs1]='^';if(isinteger(s2))/*调用函数判断s2内存到是否是整数*/printf("取余算法第二个数应为整数运算\n");flag=1;/*记录为有错*/chestr[i+indexs2]='^';i++;c=str[i];/*检索下一个字符*/if(che.size>0){/*如果最后栈不为空*/printf("缺少右括号\n");/*栈中还有没配对的左括号报错*/returnflag;/*返回是否有错*/intisinteger(charinteger[100])/*判断数组内是否是整数*/inti=0;/*传过来的数组的索引*/charc;c=integer[i++];while(c!='\0')/*直到字符串最后扫描结束*/if(c=='.')/*只要有一个字符为小数点就不是整数*/return1;elsec=integer[i++];/*扫描下一个*/return0;运行结果在输入表达式没有错误的情况下,可以得到两种算法的运算结果为:图5表达式正确时两种算法运行结果图如果表达式的输入有错误,运行结果分别如下:1.除数为0图6除数为0提示错误图取余运算操作数不为整数:图7取余操作数不为整提示错误图3.括号匹配的问题:图8缺少左括号提示错误图图9缺少右括号提示错误图五、遇到的问题及解决在编程的时候总是会有很多的意想不到的为题出现。这部分我主要遇到了如下两个问题,其内容与解决方法如下所列:将字符表示的数字转化为浮点数这个操作的主要目的就是数字是用一串字符表示的,在计算的过程中就要把字符串转化成对应的浮点数,要解决这个问题,首先查找C语言的库函数,其中找到一个可以将字符串转化为浮点数的函数atof()。那么就需要将数值的一串字符存入预定的数组中。利用循环到时可以得到要求,但是总是出现如下情况:图10转化为浮点时的错误出现这种情况,首先确定后缀表达式是正确的,但在后缀表达式的计算时出现了错误,导致结果出错。检查程序,没有语法错误。逐步打印可以看到的结果,发现在利用atof后用printf函数打印时出现了错误,最后才发现是因为在每一次调用atof时都要将一串字符存入trans数组,可是,每次存储结束时,却忘记将trans数组的索引重新设为0,这就导致了数组中是多个数都存到了数组中,然后就把数组转化为浮点数,导致了浮点数不是应得的数值。只要将trans的数组索引i每次都归零就可以了。在将中缀转化为后缀表达式的过程中,得不到结果得到用户输入的中缀表达式后调用函数,目的是得到后缀表达式可是总是出现如下的情况:图11转化为浮点时的错误由于学习C语言的时候使用的编译器是WINTC而这次编程使用的是VC,询问过用VC的人之后才知道,如果字符串没有结束符号就会“喊烫”。检查程序后才知道,在将中缀转化为后缀的时候,在最后没有对字符串手动的加入'\0'来表示结束。因此,在程序的最后加入ch[k]='\0';就可以了。六、 心得体会 决胜全面小康心得体会学党史心得下载党史学习心得下载军训心得免费下载党史学习心得下载 大一就开始学习C语言,可是,当时学的时候就觉得语言好像是学会了,可是一遇到编程的问题还是头大,总感觉没有什么思路,而这次作业,给自己一个不得不动手操作的机会,在十一的这几天中,复习了以前学过的C的基本知识,然后一点一点的摸索,遇到了错误和同学一起讨论,有问题自己想办法解决,最后程序调试出来的时候,会觉得真的很高兴。我知道,我们现在的水平还很差,要想学习好这门课,在以后就要多动手操作,书上的例题或算法,最好都自己编写程序实现,那样可以加深对算法的理解,也可以提高我们编程的水平。同时,很多的东西,理解了,可是在实现的时候还是有很多的错误发生,在以后的练习和实践中,应该多动手,遇到问题多思考,即使方案不是最优的也要想办法自己解决,然后和好的方案进行比较,从中找出自己的差距在哪里。
本文档为【C语言 后缀表达式计算】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
人生旅程
暂无简介~
格式:doc
大小:121KB
软件:Word
页数:12
分类:初中语文
上传时间:2022-01-03
浏览量:3