南京师范大学泰州学院.docx
《南京师范大学泰州学院.docx》由会员分享,可在线阅读,更多相关《南京师范大学泰州学院.docx(14页珍藏版)》请在冰豆网上搜索。
![南京师范大学泰州学院.docx](https://file1.bdocx.com/fileroot1/2022-12/29/7cf1bf8b-c762-448d-a5b6-7fb2e82770f1/7cf1bf8b-c762-448d-a5b6-7fb2e82770f11.gif)
南京师范大学泰州学院
南京师范大学泰州学院
2014—2015学年第一学期
课程名称数据结构
设计题目表达式求值
专业班级计算机科学与技术1301
姓名刘志豪
学号09130133
指导教师李橙
2015年1月6日
目录
一.设计题目………………………………………………………………………3
二.需求分析………………………………………………………………………3
三.概要设计………………………………………………………………………3
四.基本算法………………………………………………………………………4
五.测试结果………………………………………………………………………7
六.源代码…………………………………………………………………………8
七.心得体会………………………………………………………………………12
一设计题目
表达式求值(中缀)
二需求分析
2.1问题描述:
在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,在程序设计时,借助栈实现。
2.2表达式求值程序分析:
主要利用栈和数组,把运算的先后步骤进行分析并实现简单的运算,以字符列的形式从终端输入语法的正确的、不含变量的整数表达式。
利用已知的算符优先关系,实现对算术四则运算的求值,在求值中运用栈、运算栈、输入字符和主要操作的变化过程。
该程序相当于一个简单的计算机计算程序,只进行简单的加减乘除和带括号的四则运算。
三概要设计
3.1基本思想(中缀表达式求值)
要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式,要了解算术四则运算的规则即:
a先乘除后加减;
b从左到右计算;
c先括号内,后括号外。
下表定义的运算符之间的关系:
b
a
+
-
*
/
(
)
#
+
>
>
<
<
<
>
>
_
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
为了实现运算符有限算法,在程序中使用了两个工作栈。
分别是:
运算符栈OPTR,操作数栈OPND.
基本思想:
(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;
(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈得栈顶运算符比较优先级后作相应操作。
若大于栈顶元素优先级则如栈,若小于栈顶元素优先级则退出和OPND得操作数进行计算,并把计算结果如OPND栈。
直至整个表达式求值完毕(即OPND栈的栈顶元素和当前读入的字符均为“#”)。
3.2栈的抽象数据类型的定义:
ADTStack{
数据对象:
D={ai|ai∈IntegerSet,i=1,2,…,n,n≥0}
数据关系:
R1={〈ai-1,ai〉|ai-1,ai∈D,i=1,2,…,n}
约定an端为栈顶,ai端为栈底
四.操作算法
4.1基本操作思想:
InitStack(&S)
操作结果:
构造一个空栈S。
DestroyStack(&S)
初始条件:
栈S已存在。
操作结果:
栈S被销毁。
ClearStack(&S)
初始条件:
栈S已存在。
操作结果:
将S清为空栈。
StackEmpty(S)
初始条件:
栈S已存在。
操作结果:
若栈S为空栈,则返回True,否则返回False。
StackLength(S)
初始条件:
栈S已存在。
操作结果:
返回S的元素个数,即栈的长度。
GetTop(S,&e)
初始条件:
栈S已存在且非空。
操作结果:
用e返回S的栈顶元素。
Push(&S,e)
初始条件:
栈S已存在。
操作结果:
插入元素e为新的栈顶元素。
Pop(&S,&e)
初始条件:
栈S已存在且非空。
操作结果:
删除S的栈顶元素,并用e返回其值。
StackTraverse(S,visit())
初始条件:
栈S已存在且非空。
操作结果:
从栈底到栈顶依次对S的每个数据元素调用函数visit()。
一旦visit()失败,则操作失败。
}ADTStack
4.2基本操作
中缀表达式求值,在转换和计算中主要用到了下列几个函数
1)charPrecede(chart1,chart2)
作用:
判断运算符t1和t2的优先关系。
如:
case'+':
case'-':
if(t1=='('||t1=='#')
f='<';//t1else
f='>';//t1>t2
break;
2)boolIsOperator(charc)
作用:
判断c是否为7种运算符之一
boolIsOperator(charc)//判断c是否为7种运算符之一
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
returntrue;
default:
returnfalse;
}
}
3)intOperate(inta,charoper,intb)
作用:
intOperate(inta,charoper,intb)
{
switch(oper)
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
default:
break;
}
returna/b;
}
4)intEvaluateExpression()
作用:
中缀表达式求值的算法
intEvaluateExpression()
{
stackOPTR,OPND;//设置操作数栈和操作符栈
inta,b,d,x;
charc;
OPTR.push('#');
c=getchar();
x=OPTR.top();
while(c!
='#'||x!
='#')
{
if(IsOperator(c))
{
switch(Precede(x,c))
{
case'<':
OPTR.push(c);
c=getchar();
break;
case'=':
x=OPTR.top();
OPTR.pop();
c=getchar();
break;
case'>':
x=OPTR.top();
OPTR.pop();
b=OPND.top();
OPND.pop();
a=OPND.top();
OPND.pop();
OPND.push(Operate(a,x,b));
}
}
elseif(c>='0'&&c<='9')
{
d=0;
while(c>='0'&&c<='9')
{
d=d*10+c-'0';
c=getchar();
}
OPND.push(d);
}
else
{
cout<<"出现非法字符"<exit(0);
}
x=OPTR.top();
}
x=OPND.top();
if(OPND.empty())
{
cout<<"表达式不正确#"<exit(0);
}
returnx;
}
五测试结果
六.源代码
#include
#include
usingnamespacestd;
intEvaluateExpression();
intmain()
{
cout<<"请输入算术表达式,负数要用(0--正数)表示\n";
cout<return0;
}
charPrecede(chart1,chart2)
{//判断t1,t2两符号的优先关系('#'用'#'代替)
charf;
switch(t2)
{
case'+':
case'-':
if(t1=='('||t1=='#')
f='<';//t1else
f='>';//t1>t2
break;
case'*':
case'/':
if(t1=='*'||t1=='/'||t1==')')
f='>';//t1>t2
else
f='<';//t1break;
case'(':
if(t1==')')
{
cout<<"括号不匹配"<exit(0);
}
else
f='<';//t1break;
case')':
switch(t1)
{
case'(':
f='=';//t1=t2
break;
case'#':
cout<<"缺乏左括号"<exit(0);
default:
f='>';//t1>t2
}
break;
case'#':
switch(t1)
{
case'#':
f='=';//t1=t2
break;
case'(':
cout<<"缺乏右括号"<exit(0);
default:
f='>';//t1>t2
}
}
returnf;
}
boolIsOperator(charc)//判断c是否为7种运算符之一
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
returntrue;
default:
returnfalse;
}
}
intOperate(inta,charoper,intb)
{//做运算athetab,返回运算结果
switch(oper)
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
default:
break;
}
returna/b;
}
intEvaluateExpression()
{
stackOPTR,OPND;//设置操作数栈和操作符栈
inta,b,d,x;
charc;
OPTR.push('#');
c=getchar();
x=OPTR.top();
while(c!
='#'||x!
='#')
{
if(IsOperator(c))
{
switch(Precede(x,c))
{
case'<':
OPTR.push(c);
c=getchar();
break;
case'=':
x=OPTR.top();
OPTR.pop();
c=getchar();
break;
case'>':
x=OPTR.top();
OPTR.pop();
b=OPND.top();
OPND.pop();
a=OPND.top();
OPND.pop();
OPND.push(Operate(a,x,b));
}
}
elseif(c>='0'&&c<='9')
{
d=0;
while(c>='0'&&c<='9')
{
d=d*10+c-'0';
c=getchar();
}
OPND.push(d);
}
else
{
cout<<"出现非法字符"<exit(0);
}
x=OPTR.top();
}
x=OPND.top();
if(OPND.empty())
{
cout<<"表达式不正确#"<exit(0);
}
returnx;
}
}while(ir[i]=r[0];
c++;
q(r,s,j-1);
q(r,j+1,t);
}
}
七附录和设计心得体会
这是一门纯属于设计的科目,它需用把理论变为上机调试。
在学习科目的第一节课起,李老师就为我们阐述了它的重要性。
它对我们来说具有一定的难度。
它是其它编程语言的一门基本学科。
刚开始学的时候确实有很多地方我很不理解,每次上课时老师都会给我们出不同的设计题目,对于我们一个初学者来说,无疑是一个具大的挑战,撞了几次壁之后,我决定静下心来,仔细去写程序。
老师会给我们需要编程的内容一些讲解,顺着老师的思路,来完成自己的设计,我们可以开始运行自己的程序,可是好多处的错误让人看的可怕,还看不出到底是哪里出现了错误,但是程序还是得继续下去,我多次请教了老师和同学,逐渐能自己找出错误,并加以改正。
检查错误都是用英文来显示出来的,经过了这次课程设计,现在已经可以了解很多错误在英文里的提示,这对我来说是一个突破性的进步,眼看着一个个错误通过自己的努力在我眼前消失,觉得很是开心。
此次的程序设计能够成功,是我和我的同学共同努力作用的结果。
在这一段努力学习的过程中,我们的编程设计有了明显的提高。
其实现在想起来,收获还真是不少,虽然说以前非常不懂这门语言,在它上面花费了好多心血,觉得它很难,是需用花费了大量的时间编写出来的。
现在真正的明白了一些代码的应用,每个程序都有一些共同点,通用的结构,相似的格式。
只要努力去学习,就会灵活的去应用它。