算术表达式求值演示课程设计报告.docx
《算术表达式求值演示课程设计报告.docx》由会员分享,可在线阅读,更多相关《算术表达式求值演示课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
![算术表达式求值演示课程设计报告.docx](https://file1.bdocx.com/fileroot1/2022-11/25/9f449cce-5d1a-4b68-89ac-b92ab0cbd1d5/9f449cce-5d1a-4b68-89ac-b92ab0cbd1d51.gif)
算术表达式求值演示课程设计报告
题目:
算术表达式求值演示
班级:
031021班姓名:
李鑫学号:
03102067完成日期:
2011.12
一、需求分析
1.问题描述:
表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的一个经典例子。
设计一个程序演示用算符优先法对算术表达式求值的过程。
2.基本要求:
利用教科书表3.1给出的算符优先关系,实现对算术四则混合运算表达式的求值。
3.测试数据:
教科书例3-1的算术表达式3*(7-2)。
二、概要分析
栈的抽象数据类型定义
ADTSqStack{
数据对象:
D={ai|ai∈ElemSet,i=1,2,3……,n,n≥0}
数据关系:
R1={|ai-1,ai∈D,i=1,2,3,……,n}
约定其中ai端为栈底,an端为栈顶。
操作集合:
(1)voidInitStack1(SqStack1&S1);//声明栈建立函数
(2)voidInitStack2(SqStack2&S2);//声明栈建立函数
(3)voidevaluate(SqStack1&S1,SqStack2&S2);//确定如何入栈函数
(4)voidPush1(SqStack1&S1,chare);//声明入栈函数
(5)voidPush2(SqStack2&S2,floate);//声明入压栈函数
(6)charGetTop1(SqStack1&S1);//声明取栈顶元素函数
(7)floatGetTop2(SqStack2&S2);//声明取栈顶元素函数
(8)charPop1(SqStack1&S1);//声明出栈函数
(9)floatPop2(SqStack2&S2);//声明出栈函数
(10)charCompare(charm,charn);//声明比较函数
(11)floatOperate(floata,charrheta,floatb);//声明运算函数
(12)voidDispStack1(SqStack1&S1);//从栈底到栈顶依次输出各元素
(13)voidDispStack2(SqStack2&S2);//从栈底到栈顶依次输出各元素
}ADTSqStack
三、详细设计
源程序
#include
usingnamespacestd;
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT10
typedefstruct//运算符栈
{
char*base;
char*top;
intstacksize;
}SqStack1;
typedefstruct//运算数栈
{
float*base;
float*top;
intstacksize;
}SqStack2;
voidInitStack1(SqStack1&S1);//声明栈建立函数
voidInitStack2(SqStack2&S2);//声明栈建立函数
voidevaluate(SqStack1&S1,SqStack2&S2);//确定如何入栈函数
voidPush1(SqStack1&S1,chare);//声明入栈函数
voidPush2(SqStack2&S2,floate);//声明入压栈函数
charGetTop1(SqStack1&S1);//声明取栈顶元素函数
floatGetTop2(SqStack2&S2);//声明取栈顶元素函数
charPop1(SqStack1&S1);//声明出栈函数
floatPop2(SqStack2&S2);//声明出栈函数
charCompare(charm,charn);//声明比较函数
floatOperate(floata,charrheta,floatb);//声明运算函数
voidDispStack1(SqStack1&S1);//从栈底到栈顶依次输出各元素
voidDispStack2(SqStack2&S2);//从栈底到栈顶依次输出各元素
/*主函数*/
voidmain()
{
SqStack1S1;//定义运算符栈
SqStack2S2;//定义运算数栈
//freopen("data1.in","r",stdin);
//freopen("data1.out","w",stdout);
InitStack1(S1);//调用栈建立函数
InitStack2(S2);//调用栈建立函数
evaluate(S1,S2);//调用确定如何入栈函数
cout<<"按任意键结束!
"<}
/*运算符栈函数*/
voidInitStack1(SqStack1&S1)//构造一个空栈S1
{
S1.base=(char*)malloc(STACK_INIT_SIZE*sizeof(char));
if(!
S1.base)cout<<"存储分配失败!
";//存储分配失败
S1.top=S1.base;
S1.stacksize=STACK_INIT_SIZE;
}
voidPush1(SqStack1&S1,chare)//入栈
{
if(S1.top-S1.base>=S1.stacksize)//如果栈满,追加存储空间
{
S1.base=(char*)realloc(S1.base,(S1.stacksize+STACKINCREMENT)*sizeof(char));
if(!
S1.base)cout<<"存储分配失败!
";
else
{
S1.top=S1.base+S1.stacksize;
S1.stacksize=S1.stacksize+STACKINCREMENT;
}
}
*S1.top=e;S1.top=S1.top+1;//将元素压入栈中,指针上移
}
charGetTop1(SqStack1&S1)//取栈顶元素
{
chare;
if(S1.top==S1.base)cout<<"\n\t\t\t运算符栈已空!
\n";
elsee=*(S1.top-1);
returne;
}
voidDispStack1(SqStack1&S1)//从栈底到栈顶依次输出各元素
{
chare,*p;
if(S1.top==S1.base)cout<<"";
else
{
p=S1.base;
while(p{
e=*p;
p++;
cout<}
}
}
charPop1(SqStack1&S1)//出栈
{
chare;
if(S1.top==S1.base)cout<<"\n\t\t\t运算符栈已空!
\n";
e=*(--S1.top);
returne;
}
/*运算数栈函数*/
voidInitStack2(SqStack2&S2)//构造一个空栈S2
{
S2.base=(float*)malloc(STACK_INIT_SIZE*sizeof(float));
if(!
S2.base)cout<<"存储分配失败!
";//存储分配失败
S2.top=S2.base;
S2.stacksize=STACK_INIT_SIZE;
}
voidPush2(SqStack2&S2,floate)//入栈
{
if(S2.top-S2.base>=S2.stacksize)//栈满,追加存储空间
{
S2.base=(float*)realloc(S2.base,(S2.stacksize+STACKINCREMENT)*sizeof(float));
if(!
S2.base)cout<<"存储分配失败!
";
else
{
S2.top=S2.base+S2.stacksize;
S2.stacksize=S2.stacksize+STACKINCREMENT;
}
}
*S2.top=e;S2.top=S2.top+1;//将元素e入栈,指针上移
}
voidDispStack2(SqStack2&S2)//从栈底到栈顶依次输出各元素
{
floate,*p;
if(S2.top==S2.base)cout<<"";
else
{
p=S2.base;
while(p{
e=*p;
p++;
cout<}
}
}
floatGetTop2(SqStack2&S2)//取栈顶元素
{
floate;
if(S2.top==S2.base)cout<<"\n\t\t运算数栈已空!
";
elsee=*(S2.top-1);
returne;
}
floatPop2(SqStack2&S2)//出栈
{
floate;
if(S2.top==S2.base)cout<<"\n\t\t运算数栈已空!
";
e=*(--S2.top);
returne;
}
/*确定如何入栈函数*/
voidevaluate(SqStack1&S1,SqStack2&S2)
{
charc;
floatt,e;
intn=0,i=1,j=0,k=0,l=0;
charch[STACK_INIT_SIZE];
ints=1;
intflag=0,flag2=0;
floatp1,p2;
charch1;
Push1(S1,'#');//将'#'入栈,作为低级运算符
cout<<"请输入不含变量的表达式(以#结束!
):
\n";
cin>>ch;
c=ch[0];
cout<<"\n对表达式求值的操作过程如下:
"
<<"\n________________________________________________________________________________\n"
<<"步骤\t运算符栈S1\t运算数栈S2\t输入字符\t\t主要操作";
while(c!
='#'||GetTop1(S1)!
='#')
{
cout<<"\n________________________________________________________________________________\n";
cout<
DispStack1(S1);cout<<"\t\t";
DispStack2(S2);
cout<<"\t\t";
if(flag==1)
{
k--;
flag=0;
}
if(flag2)
{
k+=flag2;
flag2=0;
}
for(l=0;lcout<<'';
for(j=k;ch[j]!
='\0';j++)
cout<if(ch[k]!
='#'&&flag!
=1){k++;flag=0;}
as:
if(!
(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#'))
{//输入的字符如果不是运算符号,则继续输入直到输入的是运算符为止,将非运算符转换成浮点数
if(!
(c=='.')&&n>=0)
{
e=float(c-48);
n++;
if(n==1)t=e;
elseif(n>1)t=t*10+e;
c=ch[s++];
}
if(n==-1)
{
e=float(c-48);
t=t+e/10;
c=ch[s++];
}
if(c=='.')
{
n=-1;
c=ch[s++];
}
if((c>='0'&&c<='9')||c=='.')
{
flag2++;
gotoas;
}
if(c<'0'||c>'9')
{
Push2(S2,t);
}
cout<<"\t\tPush2(S2,"<}
else//输入的是运算符
{
n=0;//非运算型数据计数器清零
switch(Compare(GetTop1(S1),c))//比较运算符的优先级
{
case'<':
//栈顶元素优先级低,则入栈且继续输入
Push1(S1,c);
cout<<"\t\tPush1(S1,"<c=ch[s++];
break;
case'=':
//栈顶元素优先级相等,脱括号并接收下一字符
Pop1(S1);
cout<<"\t\tPop1(S1)";
c=ch[s++];
break;
case'>':
//栈顶元素优先级高,则退栈并将运算结果入栈
p1=Pop2(S2);
p2=Pop2(S2);
ch1=Pop1(S1);
Push2(S2,Operate(p2,ch1,p1));
cout<<"\t\tOperate("<flag=1;
break;
}
}
}
cout<<"\n________________________________________________________________________________\n";
cout<
for(j=0;jcout<<"#"<<"\t\t"<<"RETURN(GETTOP(S2))";
cout<<"\n________________________________________________________________________________\n";
if(S2.top-1==S2.base)//显示表达式最终结果
cout<<"\n表达式的结果为:
"<elsecout<<"\n表达式出错!
\n";
}
charCompare(charm,charn)//运算符的优先级比较
{
if(n=='+'||n=='-')//输入符号为"+"、"-"
{
if(m=='('||m=='#')return'<';//栈顶元素为"("、"#",此时栈顶符号优先级低,返回"<"
elsereturn'>';//否则,栈顶符号优先级高,返回">"
}
elseif(n=='*'||n=='/')//输入的符号为"*"、"/"
{
if(m==')'||m=='*'||m=='/')return'>';//栈顶元素为")"、"*"、"/",此时栈顶符号优先级高,返回">"
elsereturn'<';//否则,栈顶符号优先级低,返回"<"
}
elseif(n=='(')return'<';//输入的符号为"(",则直接返回"<"
elseif(n==')')//输入的符号为")"
{
if(m=='(')return'=';//栈顶元素为"(",此时优先级同,返回"="
elsereturn'>';//否则,栈顶符号优先级高,返回">"
}
else//输入符号为其他
{
if(m=='#')return'=';//栈顶元素为"#",此时优先级同,返回"="
elsereturn'>';//否则,栈顶符号优先级高,返回">"
}
}
floatOperate(floata,chartheta,floatb)//运算函数
{
floattmp=0;
if(theta=='+')tmp=a+b;//从运算符栈取出的符号为"+",则运算数栈的两元素相加,并返回
elseif(theta=='-')tmp=a-b;//从运算符栈取出的符号为"-",则运算数栈的两元素相减,并返回
elseif(theta=='*')tmp=a*b;//从运算符栈取出的符号为"*",则运算数栈的两元素相乘,并返回
elseif(theta=='/')//从运算符栈取出的符号为"/",则运算数栈的两元素相除,并返回
{
if(b==0)cout<<"\n表达式出错!
除数不能为0!
\n";
elsetmp=a/b;
}
returntmp;
}
四.调试分析
五、总结与心得
经过两个星期的实际操作和搜索相关资料,终于让我完成了任务。
让我对《数据结构》C语言有了更进一步的认识和了解,也让我知道,要想学好它要重在实践,理论与实际应用相结合,提高了自己组织数据及编写大型程序的能力,培养了基本的、良好的程序设计技能以及合作能力。
通过实际操作,我也发现我的好多不足之处:
(1)用栈的结构来解决表达式的求值,首先要解决的问题是如何将人们习惯书写的表达式转换成计算机容易处理的表达式。
开始有些茫然,后来通过结合课本和同学的帮助完成了该课题。
(2)对一些看似简单的东西掌握不够熟练,比如由于函数的调用参数问题不熟而造成了调试的困难。
对于语法的掌握也欠缺成熟,需要进一步掌握。
(3)栈的结构理解不够清晰,造成了设计程序时理不清头绪,需要对数据结构有更深层次的理解。