您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 交通运输 > 北京理工大学-数据结构-实验报告-实验二--简易计算器
实验二简易计算器姓名:任子龙学号:1120140167班级:05111451一.需求分析1.程序要求可对一实数算术表达式进行简单的数学运算,可以识别带+、-、*、/、%、^(乘方)等等运算符及括号的中缀表达式,从键盘上输入一算术表达式(一般为中缀表达式),计算出表达式的值。2.按照四则运算规则,求表达式的值。一般规则如下:1)先括号内,再括号外。2)先乘方,再乘除,后加减。b.同级运算从左到右顺序执行。3.有良好的提示信息,引导用户在键盘上输入规定的运算指令;如表达式有误,也应给出相应的提示信息。4.建立两个工作栈,分别保存运算符,操作数或运算结果。二.概要设计1.抽象数据类型的定义为实现上述功能,建立两个工作栈;算符为字符型变量,算数为单精度浮点型变量,则需要定义两种数据类型分别存储。typedefstructStackChar{charc;structStackChar*next;}SC;typedefstructStackFloat{floatf;structStackFloat*next;}SF;2.本程序包含两个模块(1)主程序模块主函数只包含了输入输出部分。流程为:首先输入算式,然后调用算符优先算法函数EvaluateExpression(s)进行计算,结果输出;然后循环下去,直到输入OUT指令,退出程序;(2)链栈单元模块——实现栈的链式存储的抽象数据类型。各函数之间的调用关系:三.详细设计1.结点类型typedefstructStackChar{charc;structStackChar*next;}SC;typedefstructStackFloat{floatf;structStackFloat*next;}SF;2.子函数(1)算符优先算法的主干函数floatEvaluateExpression(char*e)实现算符优先算法主干的函数。首先判断是算符还是算数,如果是算符,与算符栈栈顶元素进行优先级比较,如果该算符优先级比原栈顶元素优先级高,则进栈,否则进行运算;如果是算数,则入算数栈。(2)进栈出栈函数SC*Push(SC*s,charc);//使算符c进入算符栈SF*Push(SF*s,floatf);//使数值f进入数值栈SC*Pop(SC*s);//使算符栈的栈顶元素出栈SF*Pop(SF*s);//使数值栈的栈顶元素出栈分别实现算符和数值的进栈和出栈操作,由EvaluateExpression函数直接调用。(3)运算函数floatOperate(floata,unsignedchart,floatb);进行运算,a,b为数,t为运算符,进行加减乘除或乘方运算,返回值为运算的结果。(4)类型判断函数StatusIn(charTest,char*TestOp);判断是不是运算符,返回是或不是。(5)优先级判断函数charprecede(charAop,charBop);判断两个算符的优先级,返回''或''或'='。(6)运算符识别函数intReturnOpOrd(charop,char*TestOp);判断是哪个运算符。3.主函数intmain()//主函数,用来输入输出和调用子函数{chars[128],a[4]=OUT;提示信息;k:printf(\n请输入计算表达式:);scanf(%s,s);if(strcmp(s,a)){printf(\n%s\b=%g\n,s,EvaluateExpression(s));//调用算符优先算法函数gotok;}elseexit(0);}四.调试分析1.为了提高程序的健壮性,在switch语句中加了case为“?”的情况,对其它非法输入也进行考虑;2.对关于栈的基本操作,在编写过程中暴露出问题;2.如何实现按照运算法则进行计算真的特别难,好在老师在课堂上讲过算符优先算法,看到题目并不是很慌;同时也说明了编程时,好的算法意味着成功了一半。五.测试结果1.对给定的测试数据4.5+6.5*1.06=11.39,测试通过;2.对于非法的输入,如2*(1+8*9(,给出错误提示;3.输入大写OUT,直接退出程序。六.附录#includestdio.h#includestdlib.h#includestring.h#includemath.htypedefintStatus;//将int定义为自定义数据类型typedefstructStackChar{charc;structStackChar*next;}SC;//存放算符的栈typedefstructStackFloat{floatf;structStackFloat*next;}SF;//存放数值的栈charOPSET[9]={'+','-','*','/','(',')','#','^','%'};unsignedcharPrior[9][9]={//算符间的优先级表,用于算符优先算法的判断//'+''-''*''/''('')''#''^''%'/*'+'*/'','','','','','','','','',/*'-'*/'','','','','','','','','',/*'*'*/'','','','','','','','','',/*'/'*/'','','','','','','','','',/*'('*/'','','','','','=','?','','',/*')'*/'','','','','?','','','','',/*'#'*/'','','','','','?','=','','',/*'^'*/'','','','','','','','','',/*'%'*/'','','','','','','','',''};//函数的声明floatEvaluateExpression(char*e);//实现算符优先算法的函数SC*Push1(SC*s,charc);//使算符c进入算符栈SF*Push2(SF*s,floatf);//使数值f进入数值栈SC*Pop1(SC*s);//使算符栈的栈顶元素出栈SF*Pop2(SF*s);//使数值栈的栈顶元素出栈floatOperate(floata,unsignedchart,floatb);//进行运算,a,b为数,t为运算符StatusIn(charTest,char*TestOp);//判断是不是运算符,返回是或不是charprecede(charAop,charBop);//判断优先级,返回''或''或'='intReturnOpOrd(charop,char*TestOp);//判断是哪个运算符floatEvaluateExpression(char*e)//算术表达式求值的算符优先算法。{//设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。SC*OPTR=NULL;//算符栈,字符元素SF*OPND=NULL;//数值栈,实数元素charTempData[20];floatData,a,b;chartheta,*c,x,Dr[]={'#','\0'};OPTR=Push1(OPTR,'#');c=strcat(e,Dr);strcpy(TempData,\0);while(*c!='#'||OPTR-c!='#'){if(!In(*c,OPSET))//In(*c)判断是不是运算符;不是运算符则进栈{Dr[0]=*c;strcat(TempData,Dr);//字符串连接函数c++;if(In(*c,OPSET)){Data=atof(TempData);//字符串转换函数OPND=Push2(OPND,Data);strcpy(TempData,\0);}}else{switch(precede(OPTR-c,*c))//precede(chara,charb)函数比较下一个字符和栈顶元素的优先级{case''://栈顶元素优先权低OPTR=Push1(OPTR,*c);c++;break;case'='://脱括号并接收下一字符OPTR=Pop1(OPTR);c++;break;case''://退栈并将运算结果入栈theta=OPTR-c;OPTR=Pop1(OPTR);b=OPND-f;OPND=Pop2(OPND);a=OPND-f;OPND=Pop2(OPND);OPND=Push2(OPND,Operate(a,theta,b));break;case'?'://输入非法,报错提示printf(请输入正确的算术表达式!\n);exit(0);}}}returnOPND-f;}SC*Push1(SC*s,charc)//使算符c进入算符栈{SC*p=(SC*)malloc(sizeof(SC));p-c=c;p-next=s;returnp;}SF*Push2(SF*s,floatf)//使数值f进入数值栈{SF*p=(SF*)malloc(sizeof(SF));p-f=f;p-next=s;returnp;}SC*Pop1(SC*s)//使算符栈的栈顶元素出栈{SC*q=s;s=s-next;free(q);returns;}SF*Pop2(SF*s)//使数值栈的栈顶元素出栈{SF*q=s;s=s-next;free(q);returns;}floatOperate(floata,unsignedchart,floatb)//进行运算,a,b为数,t为运算符{switch(t){case'+':returna+b;case'-':returna-b;case'*':returna*b;case'/':returna/b;case'^':returnpow(a,b);case'%':{intc,d;c=b/1;d=a/1;returnd%c;}default:return0;}}StatusIn(charTest,char*TestOp)//判断是不是运算符,返回是或不是{inti=0;intflag=0;for(i=0;i9;i++){if(Test==TestOp[i])flag=1;}returnflag;}charprecede(charAop,charBop)//判断优先级,返回''或''或'='{returnPrior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];}intReturnOpOrd(charop,char*TestOp)//判断是哪个运算符{inti=0;for(i=0;i9;i++)if(op==TestOp[i])returni;}intmain()//主函数,用来输入输出和调用子函数{chars[128],a[4]=OUT;printf(*******************************************\n);printf(简易计算器\n);printf(*******************************************\n\n);printf(使用说明:\n);printf(1.输入法为英文输入法;\n);printf(2.由于不能区分负号和减号,不支持负数计算;\n);printf(3.退出程序请输入大写OUT.\n);printf(\n);k:printf(\n请输入计算表达式:);scanf(%s,s);if(strcmp(s,a)){printf(\n%s\b=%g\n,s,EvaluateExpression(s));//调用算符优先算法函数gotok;}else{printf(\n已退出计算器!);exit(0);}}
本文标题:北京理工大学-数据结构-实验报告-实验二--简易计算器
链接地址:https://www.777doc.com/doc-4840505 .html