《小型计算器》Word文档.docx
- 文档编号:7629231
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:13
- 大小:44.43KB
《小型计算器》Word文档.docx
《《小型计算器》Word文档.docx》由会员分享,可在线阅读,更多相关《《小型计算器》Word文档.docx(13页珍藏版)》请在冰豆网上搜索。
《小型计算器》Word文档
实验报告
课程名称算法与数据结构
姓名何劼
专业计算机科学与技术
部别
指导教员
日期年月日
实验项目列表
序号
实验项目名称
成绩
01
稀疏多项式
02
小型计算器
03
04
05
06
07
08
09
10
11
12
13
14
15
16
总评成绩:
教员签字:
实验报告
姓名:
何劼学号:
专业:
计算机科学与技术部别:
实验地点:
实验时间:
2012、3、20设备编号:
同组人员:
指导教员签字:
成绩:
教员评语:
一、实验名称
编写模拟小型计算器功能的程序。
二、实验目的
1.掌握栈的应用。
2.掌握“拼数”技术。
3.掌握字符串处理方法。
三、实验内容和要求
(1)完成对正整数的加减乘除运算,不进行错误检查。
输入一个数,一个运算符和另一个数,按=键和Enter键。
输出计算结果。
例如,输入:
123+305=
按Enter键后,输出计算结果。
(2)完成正整数的混合四则运算,要考虑优先级,但算式中不带括号,程序不作错误检查。
例如,输入:
12+34*54-21/3=
按Enter键后,输出计算结果。
(3)完成实数的混合四则运算,不作错误检查。
(4)完成带括号的混合四则运算,不作错误检查。
例如,输入:
12*(2+4)/5=
按Enter键后,输出计算结果。
(5)完成带负数,带数学函数的混合四则运算。
例如,输入:
-12.3+sin(0.12)=
按Enter键后,输出计算结果。
这一层主要练习如何处理负数和函数等“一目”运算。
(6)完成带错误检查的.用于任一数学表达式的计算。
当检查到错误时.最好指明错误的位置和出错原因。
例如,在第5个字符处少右括号、或少运算符、多运算符、数值中出现字母等非数值字符。
四、实验环境
1.硬件环境:
PC机
2.软件环境:
Windows操作系统,VC++集成开发环境
五、算法设计思想
题目的第一级即一个简单的整数拼数函数,所以程序主要问题是从第二级开始的。
模拟人脑的进行正整数四则运算的过程,设计者发现,运算符的运算优先次序与栈的“后进先出”特点是相切合的,所以整个程序是建立在栈结构的基础之上的。
但是,运算式是由数字和和运算符构成的,所以建立了一个数栈(num)一个符号栈(symb)。
当扫描指针扫描到数时,调用拼数函数,然后将得到的数字进入数栈;反之扫描到符号时,则需调用优先级比较函数(judge),比较符号栈顶的符号和扫描到的符号的优先级。
若后者优先级大于前者,则扫描到的运算符入栈,扫描指针后移;如果栈顶元素优先级高于扫描到的函数,则调用计算函数(count)进行计算。
Count函数将弹出符号栈中的栈顶元素和数栈的两个元素,然后两者进行弹出的运算符所对应的计算。
得到的结果存入数栈,然后扫描指针后移。
当符号栈中的元素为空并且扫描指针指向“=”号时,输出结果。
第二级运算实现。
第三级只是将前一级中的拼数函数进行了补充修改,用以实现实数的拼数问题。
这里就不加赘述了。
第四级是要求完成带括号的运算。
设计者对括号进行了以下条件限制:
●左括号直接入栈;
●左、右括号优先级均比一般运算符(+、-、*、/、^)低;
●扫描指针为右括号并且符号栈栈顶元素为左括号时,左括号出栈,扫描指针后移。
通过这三条即可使得括号里面的内容先进行计算。
第五级要求实现负数、sin()等一目运算。
当扫描到字母时,调用转换函数(change2),将输入的字母字符串和负号转换为对应的单个字符运算符(这样便于judge函数的判断和count函数的计算)。
然后根据具体运算先后次序补充judge函数优先级,补充count函数。
即实现了一目运算。
六、主要问题与解决方法
(一)当程序刚调试完成时,整个程序代码很混乱,if语句的嵌套过多。
其中单单求解函数(result)长度就多达130行,使人阅读起来非常的不方便。
于是,设计者根据需要,将拼数函数、字符串转换函数、优先级比较函数和计算函数单独提取了出来,并且加上了一些必要的备注,增加了程序的可读性,便于日后查看修改。
(二)实现第二级时,当第一个符号入栈时,符号栈为空,无法做优先级比较。
所以设计者一开始便在符号栈的栈底填入了一个“#”,其优先级最低。
输入字符串
sin
cos
tan
负号(-)
对应运算符
s
c
t
f
(三)当扫描指针读取到sin的时候,实际上是读到的s、i、n单个字符,于是编写了change2函数,以实现类似于拼数函数的功能。
一开始设计者考虑的是用字符数组的结构,通过指针扫描的方式实现,但在实际编写过程中发现这样做过于复杂且问题太多,考虑到数学函数名较短的特点,便直接采用了条件结构if加&&符号的方式实现。
对应关系如下:
(四)为了方便用户连续计算,于是在主函数里面加入了选择循环的指令,使用户使用更加方便。
七、实验结果
程序实现了题目第一到五级的要求,运算结果保留两位小数。
以下是实际运算界面的截图:
第一级
第二级
第三级
第四级
第五级
第六级查错(不完全)
而对于题目的第六级,目前设计者的思路是编写一个检查函数(check),然后根据运算式的合法规则,对原字符数组进行检查。
但由于需要考虑的问题很多,所以暂时没有能够实现。
八、体会、质疑、建议
通过这次小型计算器程序的编写,我对栈的概念有了更深的认识,特别是对于栈独特的结构特点有了进一步的认识。
而刚拿到实验题目的时候,我只有一些片段性的思路,然而需要考虑的问题却太多,使得自己一时间无从下手。
后来,根据题目的步步深入,一级一级的实现,发现问题竟变得简单了许多。
这也给了我一个启示:
以后面对问题时,要学会将问题分块、分步骤的思考解决,或许会更加容易。
另外,这是个程序也是我们所遇到过的比较复杂的一个程序,这个程序的完成,使得自己更有信心完成后续的课程。
最后,还有一个小插曲。
由于前一份实验报告因为系统还原丢失了,需要手工输入的字又比较多,所以我就想找一个可以识别图片上的文字的软件。
到XX上查了一下,竟然还专门有这样一门名叫0CR光学字符识别的技术。
下载了相关软件后,我将课本上的文字用数码相机照了下来,然后运行了软件,将其成功的转化成了电子稿。
这也算我做这个实验一个收获吧!
九、源代码
.cpp文件连接
/***********************************************************/
/*本程序可继续添加单目和双目的运算如arcsin(),arccos()等等*/
#include
#include
#include
#include
#defineN100//多项式的字符长度
#defineSUCC1
#defineFAIL0
unsignedm=50;//栈的初始长度
unsigneddelta=10;//栈的追加长度
typedefchareletype1;
typedefeletype1*eptr1;
typedefdoubleeletype2;
typedefeletype2*eptr2;
eptr1p1;
eptr2p2;
voidnumpush(eptr2&p2,eptr2&top2,eletype2x)//数栈进栈函数
//p2为数栈的起始指针
//top2为数栈栈顶指针
//x为进栈的数
{if(top2==p2+m)
{m+=delta;
p2=(eptr2)realloc(p2,m*sizeof(eletype2));
top2=p2+m-delta;
}
top2++;
*top2=x;
}
intnumpop(eptr2&p2,eptr2&top2,eletype2&x)//数栈出栈函数
//p2为数栈的起始指针
//top2为数栈栈顶指针
//x用来记录出栈的数
{
if(top2==p2)returnFAIL;
x=*top2;
top2--;
returnSUCC;
}
voidsymbpush(eptr1&p1,eptr1&top1,eletype1x)//符号栈进栈函数
//p1为字符栈的起始指针
//top1为字符栈栈顶指针
//x为进栈的字符
{if(top1==p1+m)
{m+=delta;
p1=(eptr1)realloc(p1,m*sizeof(eletype1));
top1=p1+m-delta;
}
++top1;
*top1=x;
}
intsymbpop(eptr1&p1,eptr1&top1,eletype1&x)//符号栈出栈函数
//p1为字符栈的起始指针
//top1为字符栈栈顶指针
//x用来记录出栈的字符
{
if(top1==p1)returnFAIL;
x=*top1;
top1--;
returnSUCC;
}
intjudge(charp,chara)//存优先级表以及做优先级比较的函数
{
eletype1symb[]={'+','-','j','s','c','t','*','/','^','=','#','(',')'};
intfirst[]={2,2,3,4,4,4,5,5,6,0,-1,1,1};
inti=0,j=0;
while(a!
=symb[i])i++;
while(p!
=symb[j])j++;
if(first[i]>first[j])return(SUCC);
elsereturn(FAIL);
}
voidchange(eletype1a[],int&i,eletype2&q)//拼数函数
{eletype2r=0,r1=1;
q=0;
while(a[i]>='0'&&a[i]<='9')//拼整数部分
{q=q*10+a[i]-'0';
i++;}
if(a[i]=='.')
{i++;
while(a[i]>='0'&&a[i]<='9')//拼小数部分
{r1=r1*0.1;
r=r+(a[i]-'0')*r1;
i++;}
}
q=q+r;
}
voidchange2(eletype1a[],int&i,eletype1&w)
//单目运算返回字符的转换
{
if(a[i]=='-')
{i=i+1;w='j';}
elseif(a[i]=='s'&&a[i+1]=='i'&&a[i+2]=='n')
{i=i+3;w='s';}
elseif(a[i]=='c'&&a[i+1]=='o'&&a[i+2]=='s')
{i=i+3;w='c';}
elseif(a[i]=='t'&&a[i+1]=='a'&&a[i+2]=='n')
{i=i+3;w='t';}
}
intcheck(eletype1str[])//查错函数(不完全)
{
inti=0,l=0,r=0;
while(str[i])
{
if(str[i]=='(')
l++;
elseif(str[i]==')')//左右括号数目限制
r++;
elseif(str[i-1]>='0'&&str[i-1]<='9'&&i!
=0&&str[i+1]>='0'&&str[i+1]<='9')
//字符中出现非法字符
{if(str[i]!
='+'&&str[i]!
='-'&&str[i]!
='*'&&str[i]!
='/'&&str[i]!
='^'&&str[i]!
='.'&&!
(str[i]>='0'&&str[i]<='9'))
{printf("第%d个字符位置出现非法字符。
\n",i+1);return0;}}
i++;}
if(l elseif(l>r){printf("缺少一个右括号\n");return0;} return1; } eletype2count(eptr1&p1,eptr1&top1,eptr2&p2,eptr2&top2)//计算函数,包括单目运算和双目运算 {eletype1w; eletype2y,z; symbpop(p1,top1,w); switch(w) { case'+': numpop(p2,top2,z); numpop(p2,top2,y); z=y+z;break; case'-': numpop(p2,top2,z); numpop(p2,top2,y); z=y-z;break; case'*': numpop(p2,top2,z); numpop(p2,top2,y); z=y*z;break; case'/': numpop(p2,top2,z); numpop(p2,top2,y); z=y/z;break; case'^': numpop(p2,top2,z); numpop(p2,top2,y); z=pow(y,z);break; case'j': numpop(p2,top2,z); z=-z;break; case's': numpop(p2,top2,z); z=sin(z);break; case't': numpop(p2,top2,z); z=tan(z);break; case'c': numpop(p2,top2,z); z=cos(z);break; default: printf("error! \n");break; } return(z);} voidresult(eletype1a[]) { eptr1p1,top1; eptr2p2,top2; inti=0; eletype1w; eletype2z=0,q; top1=p1=(eptr1)malloc(m*sizeof(eletype1)); top2=p2=(eptr2)malloc(m*sizeof(eletype2)); *top1='#'; *top2=NULL; while(a[i]) { /***********************数字的处理**************************/ if(a[i]>='0'&&a[i]<='9') {change(a,i,q); numpush(p2,top2,q);//实数进栈 q=0;} /************************符号的处理**************************/ if(*top1=='#'&&a[i]=='='){printf("%7.2f\n",*top2);break;} elseif((a[i]>='a'&&a[i]<='z'||a[i]=='-')&&(i==0||! (a[i-1]>='0'&&a[i-1]<='9'||a[i-1]==')'))) {change2(a,i,w); symbpush(p1,top1,w);} elseif(*top1=='('&&a[i]==')')//左右括号相遇,则消去栈中的左括号 {symbpop(p1,top1,w); i++;} elseif(a[i]=='(')//左括号直接进栈 {symbpush(p1,top1,a[i]); i++;} elseif(judge(*top1,a[i]))//判断优先级,比栈顶元素大进栈,反之栈顶出栈 { symbpush(p1,top1,a[i]); i++; } /*********************************************************/ else {z=count(p1,top1,p2,top2); numpush(p2,top2,z);} } } voidmain() { inti,a; eletype1str[N]; printf("本计算器可执行包括+,-,*,/,^,sin(),cos(),tan()的多步科学计算。 \n结果保留两位小数。 \n"); do {printf("请输入计算式: \n"); scanf("%s",str);//输入表达式 if(check(str)) result(str);//求解函数 for(i=0;str[i]! ='\0';i++) str[i]='\0'; printf("是否继续计算? 1、是;2、否\n"); scanf("%d",&a); }while(a==1); printf("谢谢使用,再见! \n"); } (注: 素材和资料部分来自网络,供参考。 请预览后才下载,期待你的好评与关注! )
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 小型计算器 小型 计算器 Word 文档