数据结构算术表达式求值系统论文Word文件下载.docx
《数据结构算术表达式求值系统论文Word文件下载.docx》由会员分享,可在线阅读,更多相关《数据结构算术表达式求值系统论文Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
(3)表达式求值及运算结果输出功能:
用栈对后缀表达式求值,并将表达式的运算结果输出。
3概要设计
在计算机中,算术表达式由常量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
每次操作的数据或运算符都是最近输入的,这与栈的特性相吻合,故本课程设计借助栈来实现按运算符的优先级完成表达式的求值计算。
3.1算法设计
(1)算符的优先级比较函数Precede(SElemTypet1,SElemTypet2)
1.算法的基本思想:
通过已知的算符间的优先关系写出算符的优先级算法。
任意两个相继出现的算符c1和c2之间的优先关系至多是下面3种关系之一:
1)c1<
c2c1的优先权低于c2
2)c1=c2c1的优先权等于c2
3)c1>
c2c1的优先权高于c2
2.算法步骤:
2.1如果输入符号为“+”或“-”
2.1.1如果栈顶元素为“(”、“#”,此时栈顶符号优先级低,返回“<
”
2.1.2否则,栈顶符号优先级高,返回“>
2.2如果输入符号为“*”或“/”
2.2.1如果栈顶元素为“)”、“*”、“/”,此时栈顶符号优先级高,返回“>
2.2.2否则,栈顶符号优先级低,返回“<
2.3如果输入符号为“(”,则直接返回“<
2.4如果输入符号为“)”
2.4.1如果栈顶元素为“(”,此时优先级同,返回“=”
2.4.2否则,栈顶符号优先级高,返回“>
2.5输入符号为其他
2.5.1栈顶元素为“#”,此时优先级同,返回“=”
2.5.2否则,栈顶符号优先级高,返回“>
(2)确定如何入栈函数EvaluateExpression()
1.1首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素。
1.2依次读入表达式中每个字符,若是操作数则进运算数栈,若是运算符则和运算符栈的栈顶运算符比较优先后作相应操作,直至整个表达式求值完毕(即运算符的栈顶元素和当前读入的字符均为“#”)。
2.1将‘#’入栈,作为低级运算符
2.2输入不含变量的表达式(以#结束)
2.3如果c!
='
#'
||x!
2.3.1如果输入的是运算符
2.3.1.1比较运算符的优先级
1)栈顶元素优先级低,则入栈且继续输入
2)栈顶元素优先级相等,脱括号并接收下一字符
3)栈顶元素优先级高,则退栈并将运算结果入栈
2.3.2如果输入的是运算数
2.3.1.1如果输入的是单个运算数,则将该运算数存入数组中,把它看成是一个字符串,并将它转换成整型,然后压入操作数栈
2.3.1.2如果输入的是连续数字,则将该连续数字存入数组中,把它看成是一个字符串,并将它转换成整型,然后压入操作数栈
2.3.3如果输入的是非法字符,则打印“出现非法字符”
2.4如果c和x都为'
2.4.1如果运算数栈OPND不空(运算符栈OPTR仅剩'
),则打印“表达式不正确”
2.4.2否则将运算数栈OPND的栈顶元素弹出,并附到x中,再将x值返回
3.2基本模块介绍
算术表达式求值系统可以分为三个模块:
1.表达式输入功能模块——将表达式序列输入系统中
2.表达式转换功能模块——实现将中缀表达式转换成后缀表达式
3.表达式求值功能模块——实现表达式求值并输出运算结果
图1功能模块图
4详细设计
4.1栈的顺序存储表示
typedefstruct
{charstack[100];
inttop;
}SqStack;
typedefcharSElemType;
4.2基本操作函数
voidInitStack(SqStack&
S)//栈建立函数
intStackEmpty(SqStackS)//判断栈是否为空
SElemTypeEvaluateExpression()//确定如何入栈函数
voidPush(SqStack&
S,SElemTypee)//入栈函数
intGetTop(SqStackS,SElemType&
e)//取栈顶元素函数
intPop(SqStack&
S,SElemType&
e)//出栈函数
charPrecede(SElemTypet1,SElemTypet2)//比较函数
intIn(SElemTypec)//判断c是否为7种运算符之一
SElemTypeOpearte(SElemTypea,SElemTypetheta,SElemTypeb)//运算函数
voidDispStack1(SqStackS)//从栈底到栈顶依次输出各元素(运算符栈)
voidDispStack2(SqStackS)//从栈底到栈顶依次输出各元素(运算数栈)
4.3源程序清单
#include"
stdio.h"
stdlib.h"
S)
{S.top=0;
}
intStackEmpty(SqStackS)
{//若栈S为空栈,则返回TRUE,否则返回FALSE
if(S.top==0)
return1;
else
return0;
e)
{//若栈不空,则用e返回S的栈顶元素,并返回OK;
否则返回ERROR
if(S.top>
0)
{
e=S.stack[S.top-1];
return-1;
S,SElemTypee)
{//插入元素e为新的栈顶元素
100)//栈满,
printf("
栈满,出错!
"
);
else
S.stack[S.top++]=e;
{//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;
e=S.stack[--S.top];
charPrecede(SElemTypet1,SElemTypet2)
{//根据教科书表3.1,判断t1,t2两符号的优先关系('
用'
\n'
代替)
charf;
switch(t2)
case'
+'
:
case'
-'
if(t1=='
('
||t1=='
)
f='
<
'
;
//t1<
t2
>
//t1>
break;
*'
/'
)'
printf("
括号不匹配\n"
exit(0);
switch(t1)
f='
//t1=t2
case'
printf("
缺乏左括号\n"
default:
:
缺乏右括号\n"
returnf;
intIn(SElemTypec)
{//判断c是否为7种运算符之一
switch(c)
return1;
default:
return0;
SElemTypeOpearte(SElemTypea,SElemTypetheta,SElemTypeb)
{//做四则运算athetab,返回运算结果
switch(theta)
returna+b;
returna-b;
returna*b;
returna/b;
{
chare;
intp;
"
p=0;
while(p<
S.top)
{
e=S.stack[p];
p++;
printf("
%c"
e);
}
}
%d"
SElemTypeEvaluateExpression()
{//算术表达式求值的算符优先算法。
设OPTR和OPND分别为运算符栈和运算数栈
SqStackOPTR,OPND;
SElemTypea,b,d,x;
charc;
//存放由键盘接收的字符
charz[11];
//存放整数字符串
inti;
intn=1;
//步骤
InitStack(OPTR);
//初始化运算符栈OPTR和运算数栈OPND
InitStack(OPND);
Push(OPTR,'
//将换行符压入运算符栈OPTR的栈底(改)
c=getchar();
//由键盘读入1个字符到c
\n对表达式求值的操作过程如下:
\n_______________________________________________________________\n"
步骤\t运算符栈OPTR\t运算数栈OPND\t主要操作"
GetTop(OPTR,x);
//将运算符栈OPTR的栈顶元素赋给x
while(c!
)//c和x不都是"
#"
\n______________________________________________________________\n"
%d\t"
n++);
DispStack1(OPTR);
\t\t"
DispStack2(OPND);
if(In(c))//c是7种运算符之一
switch(Precede(x,c))//判断x和c的优先权
Push(OPTR,c);
Push(OPTR,%c)"
c);
c=getchar();
break;
Pop(OPTR){消去一对括号}"
Pop(OPTR,x);
//x='
且c='
情况,弹出'
给x(后又扔掉)
//由键盘读入下一个字符到c(扔掉'
Pop(OPTR,x);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Opearte(a,x,b));
//做运算axb,并将运算结果入运算数栈
Opearte(%d,%c,%d)"
int(a),x,int(b));
elseif(c>
0'
&
c<
9'
)//c是操作数
i=0;
while(c>
)//是连续数字
z[i++]=c;
z[i]=0;
//字符串结束符
d=atoi(z);
//将z中保存的数值型字符串转为整型存于d
Push(OPND,%d)"
d);
Push(OPND,d);
//将d压入运算数栈OPND
else//c是非法字符
\n出现非法字符\n"
RETURN(GetTop(OPND))"
Pop(OPND,x);
//弹出运算数栈OPND的栈顶元素(运算结果)给x
if(!
StackEmpty(OPND))//运算数栈OPND不空(运算符栈OPTR仅剩'
\n表达式不正确\n"
exit(0);
returnx;
voidmain()
请输入算术表达式,负数要用(0-正数)表示(以#结束):
\n"
\n算术表达式的求值结果为:
%d\n"
EvaluateExpression());
5系统实现
将源程序放到VisualC++6.0的环境上进行调试,调试成功后就可输入一个算术表达式,然后系统就可以显示出算术表达式的正确结果以及栈的变化过程。
例如输入:
3*(5+2)#
可以得到如下图所示结果:
图2算术表达式运行结果
6结束语
经过一段时间的实际操作和搜索相关资料,终于让我完成了本次课程报告。
让我对数据结构有了更进一步的认识和了解,也让我知道,要想学好它,要重在实践,理论与实际应用相结合,同时提高了自己组织数据及编写大型程序的能力,培养了基本的、良好的程序设计技能。
通过实际操作,我也发现我的好多不足之处:
(1)用栈的结构来解决表达式的求值,首先要解决的问题是如何将人们习惯书写的表达式转换成计算机容易处理的表达式。
开始有些茫然,后来通过结合课本完成了该课程报告。
(2)对一些看似简单的东西掌握不够熟练,比如由于函数的调用参数问题不熟而造成了调试的困难。
对于语法的掌握也欠缺成熟,需要进一步掌握。
(3)栈的结构理解不够清晰,造成了设计程序时理不清头绪,所以之后需要对数据结构有更深层次的理解。
(4)我因为不注重细节而使得运行结果发生错误:
因为没有对中英文输入进行切换。
这一点小小的错误也耽误了我几十分钟,所以说细节决定成败。
参考文献:
[1]严蔚敏,吴伟民.《数据结构》(C语言版).清华大学出版社2002
[2]严蔚敏,吴伟民.《数据结构习题集》(C语言版).清华大学出版社2002
[3]许卓群.《数据结构与算法》.高等教育出版社2004