北京理工大学 数据结构 实验报告 实验二简易计算器Word格式.docx
《北京理工大学 数据结构 实验报告 实验二简易计算器Word格式.docx》由会员分享,可在线阅读,更多相关《北京理工大学 数据结构 实验报告 实验二简易计算器Word格式.docx(10页珍藏版)》请在冰豆网上搜索。
}SC;
StackFloat{
float
f;
StackFloat
*next;
}SF;
2.本程序包含两个模块
(1)主程序模块
主函数只包含了输入输出部分。
流程为:
首先输入算式,然后调用算符优先算法函数EvaluateExpression(s)进行计算,结果输出;
然后循环下去,直到输入OUT指令,退出程序;
(2)链栈单元模块——实现栈的链式存储的抽象数据类型。
各函数之间的调用关系:
三.详细设计
1.结点类型
2.子函数
(1)算符优先算法的主干函数float
EvaluateExpression(char*
e)
实现算符优先算法主干的函数。
首先判断是算符还是算数,如果是算符,与算符栈栈顶元素进行优先级比较,如果该算符优先级比原栈顶元素优先级高,则进栈,否则进行运算;
如果是算数,则入算数栈。
(2)进栈出栈函数
SC*
Push(SC
*s,char
c);
//使算符c进入算符栈
SF*
Push(SF
*s,float
f);
//使数值f进入数值栈
Pop(SC
*s);
//使算符栈的栈顶元素出栈
Pop(SF
//使数值栈的栈顶元素出栈
分别实现算符和数值的进栈和出栈操作,由EvaluateExpression函数直接调用。
(3)运算函数float
Operate(float
a,unsigned
char
t,
float
b);
进行运算,a,b为数,t为运算符
,进行加减乘除或乘方运算,返回值为运算的结果。
(4)类型判断函数
Status
In(char
Test,char*
TestOp);
判断是不是运算符
,返回是或不是。
(5)优先级判断函数
precede(char
Aop,
Bop);
判断两个算符的优先级,返回'
>
'
或'
<
='
。
(6)运算符识别函数int
ReturnOpOrd(char
op,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,直接退出程序。
六.附录
#include<
stdio.h>
stdlib.h>
string.h>
math.h>
typedefintStatus;
//将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);
}
else
switch(precede(OPTR->
c,*c))//precede(chara,charb)函数比较下一个字符和栈顶元素的优先级
{case'
:
//栈顶元素优先权低
OPTR=Push1(OPTR,*c);
break;
case'
//脱括号并接收下一字符
OPTR=Pop1(OPTR);
break;
//退栈并将运算结果入栈
theta=OPTR->
c;
OPTR=Pop1(OPTR);
b=OPND->
OPND=Pop2(OPND);
a=OPND->
OPND=Push2(OPND,Operate(a,theta,b));
//输入非法,报错提示
printf("
请输入正确的算术表达式!
\n"
exit(0);
returnOPND->
SC*Push1(SC*s,charc)//使算符c进入算符栈
SC*p=(SC*)malloc(sizeof(SC));
p->
c=c;
next=s;
returnp;
SF*Push2(SF*s,floatf)//使数值f进入数值栈
{SF*p=(SF*)malloc(sizeof(SF));
f=f;
SC*Pop1(SC*s)//使算符栈的栈顶元素出栈
{SC*q=s;
s=s->
next;
free(q);
returns;
SF*Pop2(SF*s)//使数值栈的栈顶元素出栈
SF*q=s;
floatOperate(floata,unsignedchart,floatb)//进行运算,a,b为数,t为运算符
switch(t)
returna+b;
returna-b;
returna*b;
returna/b;
returnpow(a,b);
{intc,d;
c=b/1;
d=a/1;
returnd%c;
}
default:
return0;
StatusIn(charTest,char*TestOp)//判断是不是运算符,返回是或不是
inti=0;
intflag=0;
for(i=0;
i<
9;
i++)
if(Test==TestOp[i])
flag=1;
}
returnflag;
charprecede(charAop,charBop)//判断优先级,返回'
returnPrior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
intReturnOpOrd(charop,char*TestOp)//判断是哪个运算符
{inti=0;
i<
i++)
if(op==TestOp[i])
returni;
intmain()//主函数,用来输入输出和调用子函数
*******************************************\n"
简易计算器\n"
*******************************************\n\n"
使用说明:
1.输入法为英文输入法;
2.由于不能区分负号和减号,不支持负数计算;
3.退出程序请输入大写OUT.\n"
else{printf("
\n已退出计算器!
}