计算器专题报告.docx
- 文档编号:29854335
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:22
- 大小:205.07KB
计算器专题报告.docx
《计算器专题报告.docx》由会员分享,可在线阅读,更多相关《计算器专题报告.docx(22页珍藏版)》请在冰豆网上搜索。
计算器专题报告
专题设计(栈与队列)报告
题目:
简易计算器(栈)
小组成员:
周浩天(1120121365)
吴旭晨(1120121358)
熊威博(1120121359)
郝鑫钢(1120122756)
魏鑫(1120121357)
王俊博(1120121355)
林晟威
专题报告
问题描述
通过模拟一个简单的计算器来进行+、-、*、/、%、^(乘方)等运算,从键盘上输入一算术表达式(一般为中缀表达式),计算出表达式的值。
设计要求
编写程序,要求可对一实数算术表达式进行简单的数学运算。
可以识别带加减乘除等运算符及括号的中缀表达式。
a.按照四则运算规则,求表达式的值。
一般规则如下:
1)先括号内,再括号外。
2)先乘方,再乘除,后加减。
b.同级运算从左到右顺序执行。
c.如表达式有误,应给出相应的提示信息。
数据结构
我们解决表达式求值问题的方法是:
我们建立了两个工作栈。
一个是stack1栈,用以保存操作数或运算结果;一个是stack2栈,用以保存运算符。
运行时,通过调用calculator类中的成员函数来实现对两个工作栈的操作,从而实现对表达式值的计算。
设计与实现
总体来说,我们在设计简易计算器系统的时候定义了一个calculator类,在此类中分为两个模块——数据模块和功能模块。
数据模块方面,我们定义了两个栈结构体,分别是存放操作数和运算结果的栈stack1(简称操作数栈)和存放运算符以及界附的栈stack2(简称运算符栈);功能模块方面,我们分别定义了操作数栈和运算符栈的栈空判断函数、进栈函数和出栈函数,以及栈内和栈外的优先级判断函数、计算函数和操作函数,如上图所示。
运行系统时,我们通过运行操作函数来实现其它函数功能的调用,进而实现对操作数栈和运算符栈的操作,从而最终实现计算表达式的功能。
本系统中需要主要实现的部分为calculator类中的功能模块,其中主要包括操作数栈和运算符栈的栈空判断函数、进栈函数和出栈函数,以及栈内和栈外的优先级判断函数、计算函数和操作函数等的编码实现,具体代码如下。
1.栈空判断函数
我们分别定义了操作数栈和运算符栈的栈空判断函数,目的是为了判断是否为空栈。
若为空栈,则返回1,若不为空栈,则返回0。
代码如下:
(1)操作数栈栈空判断函数:
boolcalculator:
:
stack1empty(save1s)//判断数字栈是否为空
{if(s.top==-1)return1;
elsereturn0;}
(2)运算符栈栈空判断函数:
boolcalculator:
:
stack2empty(save2s)//判断运算符栈是否为空
{if(s.top==-1)return1;
elsereturn0;}
2.进栈函数
同栈空判断函数一样,我们也分别定义了操作数栈和运算符栈的进栈函数。
进栈函数的功能是在堆栈的顶端插入一个新元素,相当于在线性表最后的元素之后再插入一个新元素。
函数功能实现的流程为:
首先测试堆栈是否已满。
若栈顶指针top==MAX-1,表示所有位置均已占满,输出“栈已满”;若栈顶指针top 先将栈顶指针top加1,指到当前可加入新元素的位置,然后将新的元素插在此位置上,这个新插入的元素将成为新的栈顶元素。 代码如下: (1)操作数栈进栈函数: voidcalculator: : push1(save1&s,doublenum)//将数据压入数字栈 {if(s.top==MAX-1)cout<<"栈已满"< else {s.top++; s.n[s.top]=num; } } (2)运算符栈进栈函数: voidcalculator: : push2(save2&s,charop)//将运算符压入运算符栈 {if(s.top==MAX-1)cout<<"栈已满"< else {s.top++; s.n[s.top]=op; } } 三.出栈函数 同理,我们也分别定义了操作数栈和运算符栈的出栈函数。 出栈函数的功能是删除栈顶的元素。 在本系统中,我们先将栈顶元素保存,再删除栈顶结点。 函数功能实现的流程为: 首先测试堆栈是否为空栈,若为空栈,输出“栈为空”;否则将栈顶元素的值num保存在num中,再将栈顶指针减1。 代码如下: (1)操作数栈出栈函数: voidcalculator: : pop1(save1&s,double&num)//将栈顶的数据元素取出,存放在num中 {if(s.top==-1)cout<<"num栈为空"< else {num=s.n[s.top]; s.top--; } } (2)运算符栈出栈函数: voidcalculator: : pop2(save2&s,char&op)//将栈顶的运算符取出,存放在op中 {if(s.top==-1)cout<<"op栈为空"< else {op=s.n[s.top]; s.top--; } } 4.优先级判断函数 我们分别定义了栈内和栈外的优先级判断函数,其目的是为了保证表达式的运算顺序的正确从而保证运算结果的正确。 代码如下: (1)栈内优先级判断函数: intcalculator: : in(charop)//在栈内优先级的判断 {switch(op) {case'+': return2;break; case'-': return2;break; case'*': return4;break; case'/': return4;break; case'(': return-1;break; default: break; } } (2)栈外优先级判断函数: intcalculator: : out(charop)//在栈外优先级的判断 {switch(op) {case'+': return1;break; case'-': return1;break; case'*': return3;break; case'/': return3;break; default: break; } } 五.计算函数 计算函数的功能是当读入的运算符的优先级小于运算符栈顶元素的优先级时,把stack1栈中最后入栈的两个操作数弹出,并按照stack2栈栈顶元素的运算规则进行运算,结果储存在stack1栈中。 代码如下: voidcalculator: : count(doublea,charop,doubleb)//进行计算并将所得的结果压入栈顶 { doublesum; switch(op) {case'+': sum=a+b;break; case'-': sum=a-b;break; case'*': sum=a*b;break; case'/': sum=a/b;break; default: break; } push1(stack1,sum); } 6.操作函数 操作函数是系统执行main函数时调用的函数,其功能是通过对操作数栈和运算符栈的操作以及对功能函数的调用来实现表达式值的计算。 代码如下: voidcalculator: : cal(void) { inti=0,j; doublea,b,c; charexpression[MAX],operate,temp[20]; cout<<"请输入表达式: "; cin>>expression; stack1.top=-1;//清空数字栈 stack2.top=-1;//清空运算符栈 while(expression[i]! ='=')//以=号结尾 {if(isdigit(expression[i]))/*若读入的字符为数字,则继续判断下一个字符,直到下个字符不是数字或者不是小数点,即可保证该操作数是完整的小数,然后将该数入操作数栈*/ {j=0; while(isdigit(expression[i])||expression[i]=='.') {temp[j++]=expression[i];i++;} temp[j]='\0'; c=atof(temp);//char类型进行转换 push1(stack1,c);} else {if(expression[i]=='('){push2(stack2,expression[i]);i++;} else{if(expression[i]==')') {while(stack2.n[stack2.top]! ='(') {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a); } pop2(stack2,operate); i++; } elseif(expression[i]=='-'||expression[i]=='+'||expression[i]=='*'||expression[i]=='/')//若读入的字符为运算符的情况 {if(in(stack2.n[stack2.top]) {push2(stack2,expression[i]);i++;} else {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a); } } } } } while(stack2.top! =-1)//读入结束后,继续进行操作,直到运算符栈为空 {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a);} cout< } 测试与结论 测试环境: 硬件环境: 处理器Intel(R)Core(TM)i5-2410MCPU@2.30GHZ2.30GHZ;安装内存: 2.00GB 软件环境: 操作系统: windows7调试环境: CFree5.0 运行结果: (1)主界面: (2)加运算: (3)减运算: (4)乘运算: (5)除运算: (6)综合运算1: (7)综合运算2: (8)综合运算3: 总结与思考 经过我们小组成员的不懈努力,我们终于完成了简易计算器程序的设计。 回顾整个程序的设计过程,我们对我们的工作做出了如下的总结与思考: (1)工作分配较为合理,进度适中 在完成本次专题作业的过程中,我们吸取了上一次完成作业时小组成员任务分配不明,参与编程人员进度不一,缺少沟通,效率低下等教训,在任务开始之初就把任务分配明确,并且定时交流沟通自己的进度、出现的问题等,有困难大家一起帮忙解决。 因此,本次小组工作的效率和质量有了较大改善; (2)编程思路明确 我们在设计简易计算器系统的时候的中心思想是“栈为核心,两个模块,多种函数,统一处理”。 “栈为核心”指的是以对栈的操作为核心,函数的功能基于栈而设计,为栈所用,通过对栈的操作以实现表达式的求值。 “两个模块”即数据模块和功能模块。 数据模块方面,我们分别定义了操作数栈和存运算符栈;功能模块方面,我们定义了操作数栈和运算符栈的栈空判断函数、进栈函数和出栈函数,以及栈内和栈外的优先级判断函数、计算函数和操作函数。 “多种函数”也正是指我们在功能模块所定义的函数。 “统一处理”则是指通过执行操作函数cal(void)来实现其他函数的调用,进而对栈进行处理,从而实现表达式的求值。 正是基于上述的编程思路,使我们能够高效率并且正确地完成编程任务。 (3)编程过程中仍然存在着问题 虽然在我们小组成员的不懈努力之下我们成功地完成了任务,但是由于时间原因和我们编程水平的有限,我们仍然存在着不少问题。 比如说我们输入负数的格式只能是(0-x)(x为正数)。 除此之外,我们的系统界面做的也不是很完善,计算精度也有限。 我们相信,随着我们编程能力和经验的提升,我们一定可以将程序做的更加完美。 课程总结 下面的内容是我组在学习堆栈与队列一章中的一些体会: 首先要意识到编程实践的重要性。 如何合理地组织数据、高效地处理数据是提高程序效率的关键。 不同的算法思想就意味着在时间性能上存在很大的差距,你不会选择合理的数据结构、有效地组织数据,当然是无法实现使用最短的时间来解决问题。 这门课程的实践性很强,如果只是“听”和“读”,那是不可能掌握它的。 例如关于堆栈和队列的建立和函数功能的实现,如果没有很好地编程实践,就不能很好地把握这个程序的思想。 第二点我认为要理解、牢固的掌握有关的基础概念概念;我们所学习的所有内容在最开始介绍的都是它的概念,这足以表明概念的重要性,连概念都无法很好的掌握,何谈掌握这整个知识点,吃透并且很好的应用它呢? 当然对这些概念绝不是那种死记硬背,那是没用的。 有一些概念可以通过与实际相结合方法,这样我们就能很轻松的理解它。 第三点是关于这门课程的学习;对于一个数据结构,在上课时听老师讲过之后,可能感觉自己已经掌握了,但当自己再去看它时又似懂非懂的说不明白。 这就是很显然还没有掌握。 只有付出努力,才能真正掌握它。 这是绝对有效的,当多实践和编程后,不仅能更加深入领会数据结构的思想,而且还能发现算法的巧妙之处,从而能更好地学习和掌握本门课程。 附录 程序源代码: #include #include #include #defineMAX1000 classcalculator {private: structsave1 {doublen[MAX]; inttop; }stack1; structsave2 {charn[MAX]; inttop; }stack2; public: calculator(){};//空的构造函数 boolstack1empty(save1s); boolstack2empty(save2s); voidpush1(save1&s,doublenum); voidpush2(save2&s,charop); voidpop1(save1&s,double&num); voidpop2(save2&s,char&op); intin(charop); intout(charop); voidcount(doublea,charop,doubleb); voidcal(); }; boolcalculator: : stack1empty(save1s)//判断数字栈是否为空 {if(s.top==-1)return1; elsereturn0; } boolcalculator: : stack2empty(save2s)//判断运算符栈是否为空 {if(s.top==-1)return1; elsereturn0; } voidcalculator: : push1(save1&s,doublenum)//将数据压入数字栈 {if(s.top==MAX-1)cout<<"栈已满"< else {s.top++; s.n[s.top]=num; } } voidcalculator: : push2(save2&s,charop)//将运算符压入运算符栈 {if(s.top==MAX-1)cout<<"栈已满"< else {s.top++; s.n[s.top]=op; } } voidcalculator: : pop1(save1&s,double&num)//将栈顶的数据元素取出,存放在num中 {if(s.top==-1)cout<<"num栈为空"< else {num=s.n[s.top]; s.top--; } } voidcalculator: : pop2(save2&s,char&op)//将栈顶的运算符取出,存放在op中 {if(s.top==-1)cout<<"op栈为空"< else {op=s.n[s.top]; s.top--; } } intcalculator: : in(charop)//在栈内优先级的判断 {switch(op) {case'+': return2;break; case'-': return2;break; case'*': return4;break; case'/': return4;break; case'(': return-1;break; default: break; } } intcalculator: : out(charop)//在栈外优先级的判断 {switch(op) {case'+': return1;break; case'-': return1;break; case'*': return3;break; case'/': return3;break; default: break; } } voidcalculator: : count(doublea,charop,doubleb)//进行计算并将所得的结果压入栈顶 {doublesum; switch(op) {case'+': sum=a+b;break; case'-': sum=a-b;break; case'*': sum=a*b;break; case'/': sum=a/b;break; default: break; } push1(stack1,sum); } voidcalculator: : cal(void) { inti=0,j; doublea,b,c; charexpression[MAX],operate,temp[20]; cout<<"请输入表达式: "; cin>>expression; stack1.top=-1;//清空数字栈 stack2.top=-1;//清空运算符栈 while(expression[i]! ='=')//以=号结尾 {if(isdigit(expression[i]))/*若读入的字符为数字,则继续判断下一个字符,直到下个字符不是数字或者不是小数点,即可保证该操作数是完整的小数,然后将该数入操作数栈*/ {j=0; while(isdigit(expression[i])||expression[i]=='.') {temp[j++]=expression[i];i++;} temp[j]='\0'; c=atof(temp);//char类型进行转换 push1(stack1,c);} else {if(expression[i]=='('){push2(stack2,expression[i]);i++;} else{if(expression[i]==')') {while(stack2.n[stack2.top]! ='(') {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a); } pop2(stack2,operate); i++; } elseif(expression[i]=='-'||expression[i]=='+'||expression[i]=='*'||expression[i]=='/')//若读入的字符为运算符的情况 {if(in(stack2.n[stack2.top]) {push2(stack2,expression[i]);i++;} else {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a); } } } } } while(stack2.top! =-1)//读入结束后,继续进行操作,直到运算符栈为空 {pop1(stack1,a); pop1(stack1,b); pop2(stack2,operate); count(b,operate,a);} cout< } intmain() {part1: cout<<"**************************************"< cout<<"*--------欢迎使用小鑫鑫计算器--------*"< cout<<"*-------------Ver.1.0.0--------------*"< cout<<"*--------------注意事项--------------*"< cout<<"*-------输入表达式后请输入=号--------*"< cout<<"*-----如需输入负数请按照如下格式-----*"< cout<<"*------------Ex: -3=(0-3)-------------*"< cout<<"**************************************"< calculatormycal; mycal.cal(); cout<<"**************************************"< cout<<"*-------是否继续计算计算表达式? ------*"< cout<<"*--------------- cout<<"*****
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算器 专题报告