《数据结构》课程设计报告简单计算器设计Word格式文档下载.docx
《《数据结构》课程设计报告简单计算器设计Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《《数据结构》课程设计报告简单计算器设计Word格式文档下载.docx(15页珍藏版)》请在冰豆网上搜索。
综上,这就要求我们的程序分为主函数、表达式判断函数、结果计算函数。
2、概要设计
在需求分析中,我们已对程序的功能做了大致规划,但是又怎样来实现这些功能呢?
在主函数中,只需要输入输出以及对各函数进行调用就行了,所以主函数是相对简单的,只是编写程序代码是注意代码的规范性就行了!
在表达式判断中,函数接收由主函数传来的表达式的地址,然后对表达式中个字符扫描对左右括号配对即可。
而计算函数有要分成两部分了,因为输入时按照一串字符串输入的,并不是数据,所以计算机并不能直接计算,而且计算牵扯到运算符的优先级问题,这是计算机不能直接处理的,因此,我们要首先把表达式转换成其能够识别计算的后缀表达式,这就有要求用一个后缀转换来实现,其次就要对这个后缀表达式计算了,我们仍用一个函数来实现。
在处理运算符优先级问题时,我们按自己定义其优先级大小并用结构体进行存储,这样即方便理解,又方便加入一些运算符!
3、详细设计
1、主函数(main.cpp)
由于要输如一表达式,将此表达式存于一数组,考虑到程序可循环性,故判断输入的第一个字符是否等于“q”当输入为“q”是退出程序。
当不是时,调用pipei子函数对表达式进行匹配判断,不匹配是输出提示要求再次输入。
在括号匹配时,调用trans(char)将表达式进行转换成对应的后缀表达式。
然后再调用函数conprdue对后缀表达式进行计算,并将结果输出。
主函数如下:
#include<
iostream>
#include<
math.h>
usingnamespacestd;
#definemaxsize100
#include"
Pipei.cpp"
Trans.cpp"
Calcu.cpp"
intmain()
{
charexp[maxsize];
charpostexp[maxsize]={0};
cout<
<
"
Pleaseinputyourexp:
Toquitwith\"
q\"
endl;
while(scanf("
%s"
exp)!
=EOF)
{
if(exp[0]=='
q'
)return0;
else
if(pipei(exp))
trans(exp,postexp);
后缀表达式为:
<
postexp<
表达式的值为:
compvalue(postexp)<
memset(postexp,0,maxsize);
}
elsecout<
inputerror!
\n"
pleasecheckyourexpandinputagain!
return0;
}
流程图如图如下:
2、匹配函数(pipei)
本函数从主函数接收所输入的字符数组,从第一个开始对字符逐个扫描。
遇到左括号时,将左括号进栈,遇到右括号时将当前栈顶元素出栈。
直到所有元素扫描完成后,若栈内无元素则括号是匹配的,否则就是不匹配的。
流程图如下:
3、后缀表达式转换trans(数值串用数组储存并用#隔开,运算符用栈)
先按运算符的优先级设定其计算的先后顺序,用结构体储存。
在表达式括号匹配的情况下,仍然从头开始扫描,栈顶元素初始为“=”,对字符串的各字符逐个扫描,遇到运算符就将其与栈顶运算符优先级进行比较,若小于栈顶运算符优先级,则将该运算符进栈。
若相等则退栈。
若大于,则退栈并将该运算符放到后缀表达式中。
如果扫描到的是数字,则将其直接进栈并用“#”隔开,直到最后,将栈内所有元素均放入后缀字符串poltexp中
4、对后缀表达式进行计算compvalue(char*p)
数据存储:
栈,用来存储计算机过程值和结果的算法仍然是要逐个扫描分别将前两个数字转化成数值后将其进栈,当读取到运算符时,对当前栈最顶端的两个数进行该运算符的运算,并把结果放入栈顶为下次计算提供数据,直到后缀表达式扫描结束时将栈顶元素值返回。
3.调试分析
问题一:
多次计算错误
在代码初步编完并初次运行后,对于第一个表达是可以正常计算,但对于以后的各个表达式计算的结果皆不正确,仔细翻看代码后发现,原来在存储表达式的字符串在第一次输入后没有清空对以后各次计算造成了误差,因此只需在主函数中,在每次计算结束后,用memset函数把定义的字符串清空即可。
问题二:
指数运算指数的指数错误
在测试指数计算时对于指数的指数计算错误,结果仍为一阶指数的值。
首先认定错误出现在指数运算的定义中,查看后发现在对指数计算取完数值后没有将栈顶指针加一,这将导致在下一次指数运算时取的数值仍是当前栈顶元素的值。
因此,只需将栈顶元素指针减一即可,修改完后的代码为:
case'
^'
:
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.data[++st.top]=pow(b,a);
break;
问题三:
对于正负数的判断
为了能使计算时正负数能够被识别,即+3+5或-2+3都能够正确计算,在测试时查看后缀表达式即可发现只需在取负的数字前加上0即可达到正负数的计算的目的。
对于正负数的判断又分两种情况,即表达式的开头或括号内的开头。
因此,就要对表达式开头和括号内开头的字符进行判断,添加后的代码为;
/*************对正数和负数处理***********/
if(*exp=='
-'
||*exp=='
+'
)
exp--;
if((*exp=='
('
)||postexp[0]=='
\0'
postexp[i++]='
0'
;
#'
exp++;
elseexp++;
4.总结与体会
本次程序设计由赵靖老师指导、组长带领我们完成的,前后历时三个星期,我们三人接到命题后讨论决定分别做主程序main.cpp和子程序trans、compvalue。
最后组合并不断调试,发现了很多漏洞和问题,我们一一分析并解决,同时为计算器扩展了很多功能,而很多问题都是我们在一起讨论总结出来的,这我们认识到一人计短,二人计长,不管人与人的编程能力有多大的区别,但是只要有较好的编程思想和算法,一样可以为整个团队解决问题。
这次课程设计提高我们了分析和解决问题的能力,也让我们认识到了团队合作的重要性。
5、代码清单
1.匹配函数:
intpipei(charexp[])
inti=0;
chare;
sqstack*st;
initstack(st);
while(exp[i]!
='
if(exp[i]=='
)//为左括号时进栈
push(st,exp[i]);
elseif
(exp[i]=='
)'
)//为右括号时
if(Gettop(st,e)==1)
if(e!
//括号不匹配时返回
elsepop(st,e);
//将栈顶元素出栈
elsereturn(0);
i++;
//继续处理其他字符
if(st->
top==-1)return
(1);
//栈为空时
2.后缀表达式转换函数:
voidtrans(char*exp,charpostexp[])//中缀转后缀
struct
chardata[maxsize];
//存放运算符
inttop;
//栈指针
}op;
//运算符栈
//i为后缀表达式的标号
op.top=-1;
op.top++;
op.data[op.top]='
//将=进栈
while(*exp!
if(!
Inop(*exp))//不是运算符时即为数字时
while((*exp>
&
*exp<
9'
)||*exp=='
.'
postexp[i++]=*exp;
//为数字时存放在后缀表达式里
//数值串结束
switch(Precede(op.data[op.top],*exp))
case-1:
//op运算级低于exp
op.data[op.top]=*exp;
case0:
op.top--;
case1:
postexp[i++]=op.data[op.top];
while(op.data[op.top]!
postexp[i]='
3.表达式计算:
/***********计算后缀表达式值*************/
floatcompvalue(char*postexp)
doubledata[maxsize];
//计算的结果
}st;
//定义数值栈
doubled,a,b,c,f;
//中间变量
intpoint=0,zhi=1,jiech=1;
st.top=-1;
st.data[st.top]=0;
while(*postexp!
)//后缀不为空时扫描表达式
switch(*postexp)//判断后缀式字符
//取数值a
//cout<
b="
b<
//取数值b
c=a+b;
st.top++;
st.data[st.top]=c;
//将结果进栈
c=b-a;
*'
c=b*a;
/'
if(a!
=0)//判断除以零无意义
c=b/a;
\n\t除零错误!
exit(0);
!
'
for(intj=1;
j<
=a;
j++)
jiech=jiech*j;
st.data[st.top]=jiech;
default:
//后缀字符为数字
d=0;
f=0;
while((*postexp>
*postexp<
)||*postexp=='
)//处理连续数字字符
if(*postexp=='
point=1;
postexp++;
else;
if(point==0)
d=10*d+*postexp-'
//将字符转为数字
//printf("
%d\t"
pow(10,zhi));
f=f+(*postexp-'
)/pow(10,zhi);
zhi++;
point=0;
//下一个数要重新验证
zhi=1;
st.data[st.top]=d+f;
//将结果进栈
return(st.data[st.top]);
评语:
成绩:
签名:
年月日