后缀表达式求值.docx
《后缀表达式求值.docx》由会员分享,可在线阅读,更多相关《后缀表达式求值.docx(12页珍藏版)》请在冰豆网上搜索。
后缀表达式求值
1题目内容及设计要求
<1>.题目:
后缀表达式求值
<2>.设计要求:
使用模板设计后缀表达式求值,模拟一个计算器操作。
例如:
“32615-*35+=”这种表达式称为“后缀表达式”,它再不需要括号,每个运算符都出现在其操作数的后面。
使用一个存放操作数的栈,求值顺序扫描后缀表达式,每次遇到操作数便将它压入堆栈;遇到运算符,则从栈中弹出两个操作数进行计算,然后再把结果压入堆栈。
这样,等到扫描结束时,留在栈顶的整数就是所求表达式的值。
实际上,后缀表达式求值时,与数据类型有关系,所以使用模板来实现。
2总体设计
2.1总体功能框图如下:
图2-1后缀表达式求值功能图
2.2类的设计说明
UML框图如下:
图2-2Stack类的完整表示
图2-3Calculator类的完整表示
2.3主要算法流程图.
Y
N
N
N
N
Y
图2-4总体算法流程图
3程序清单及注释
//这是一个标准的堆栈模板程序,因为使用模板,所以定义在一个文件里。
#if!
defined(CPP6_H)
#defineCPP6_H
#include
#include
usingnamespacestd;
constintMaxStackSize=50;
template
classStack
{private:
Tstacklist[MaxStackSize];
inttop;//栈的大小
public:
Stack(void);
voidPush(constT&item);//压栈
TPop(void);
voidClearStack(void);//清栈
TPeek(void)const;
intStackEmpty(void)const;//判断栈空
intStackFull(void)const;//判断栈满
};
template
Stack:
:
Stack(void):
top(-1)
{}
template
voidStack:
:
Push(constT&item)
{if(StackFull())
{
cerr<<"Stackoverflow!
"<exit
(1);
}
top++;
stacklist[top]=item;
}
template
TStack:
:
Pop()
{Ttemp;
if(StackEmpty())
{
cerr<<"Attempttopopanemptystack!
"<exit
(1);
}
temp=stacklist[top];
top--;
returntemp;
}
template
voidStack:
:
ClearStack(void)
{
top=-1;
}
template
TStack:
:
Peek(void)const
{
if(top==-1)
{
cerr<<"Attempttopeekatanemptystack!
"<exit
(1);
}
returnstacklist[top];
}
template
intStack:
:
StackEmpty(void)const
{
returntop==-1;
}
template
intStack:
:
StackFull(void)const
{
returntop==MaxStackSize-1;
}
#endif
/*****************************************************************/
//这里定义一个计算器模板类,模拟后缀表达式的计算过程。
#if!
defined(CALCULATOR_H)
#defineCALCULATOR_H
#include"cpp6.h"
#include
template
classCalculator
{private:
//私有成员:
计算器栈及操作数
StackS;
voidEnter(Tnum);//存放操作数
boolGetTwoOperands(T&opend1,T&opend2);
voidCompute(charop);
public:
Calculator(void){}//计算表达式及清空计算器
voidRun(void);
voidClear(void);
};
template
voidCalculator:
:
Enter(Tnum)//在栈中存放数据值
{
S.Push(num);
}
template//从栈中取得操作数并赋值给形参。
若操作数不够,则打印出错
boolCalculator:
:
GetTwoOperands(T&opend1,T&opend2)//信息,并返回false
{
if(S.StackEmpty())
{
cerr<<"Missingoperand!
"<returnfalse;
}
opend1=S.Pop();//取右操作数
if(S.StackEmpty())
{
cerr<<"Missingoperand!
"<returnfalse;
}
opend2=S.Pop();//取左操作数
returntrue;
}
template//运算求值
voidCalculator:
:
Compute(charop)
{
boolresult;
Toperand1;Toperand2;//取两个操作数,并判断是否成功取到
result=GetTwoOperands(operand1,operand2);//若成功取到,则计算本次运算值,否则将栈清空
if(result==true)
switch(op)
{
case'+':
S.Push(operand2+operand1);break;
case'-':
S.Push(operand2-operand1);break;
case'*':
S.Push(operand2*operand1);break;
case'/':
if(operand1==0)
{
cerr<<"Divideby0!
"<S.ClearStack();
}
else
S.Push(operand2/operand1);
break;
case'^':
S.Push(pow(operand2,operand1));
break;
}
else
S.ClearStack();//出错清空计算器
}
template
voidCalculator:
:
Run(void)//读入字符串,同时对后缀表达式求值,直到读入‘=’时停止
{
charc;
Tnewoperand;
while(cin>>c,c!
='=')
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'^':
Compute(c);
break;
default:
cin.putback(c);//非运算符,则必为操作数,将字符送回
cin>>newoperand;//读入操作数并将其存入栈中
Enter(newoperand);
break;
}
}
if(!
S.StackEmpty())
cout<}
template
voidCalculator:
:
Clear(void)
{
S.ClearStack();
}
#endif
/*************************************************************/
//创建一个Calculator的对象,以便验证程序功能。
#include"calculator.h"
voidmain()
{
CalculatorCALC;
cout<<"*********************************************"<cout<<"***请先将中缀表达式形如:
32*(6-15)+35=***"<cout<<"***转化为:
***"<cout<<"***后缀表达式:
32615-*35+=***"<cout<<"*********************************************"<CALC.Run();
}
4运行结果与分析
后缀表达式求值的结果如图4-1所示。
图4-1后缀表达式求值运行结果图
分析:
首先想要运行这个程序,必须要了解怎样将平常我们习惯用的中缀表达式转换成程序可读的后缀表达式,这是最重要的。
其次就是输入后缀表达式后一定要再输入一个“=”,否则程序将无法正常输出结果。
5总结
通过《后缀表达式求值》这个课程设计,我发现自己在C++以及C语言的学习上仍存在着很多不足.至少在很多细节问题上并没有完全弄懂.对于不常用的知识点掌握的十分不牢固,虽然只是一个简单的计算器功能,却让我很吃力,而且从“中缀表达式”到“后缀表达式”需要操作者自己去转换。
其实我对这些概念也同样不是很了解,幸好有李老师耐心指导,经过多次调试终于完成了,尽管这次课程设计做的不是很成功,但是通过这次亲手操作和经过老师和同学的交流学到了挺多东西的。
最起码对堆栈和模板的使用有了更为深入的理解。
在这个过程真的想放弃,但是坚持后的成功会告诉你。
其实成功并不是那么遥远,只要你坚持不懈。
参考文献
[1]李爱华,程磊著.面向对象程序设计(C++语言).北京:
清华大学出版社,2010
[2]陈清华,朱红著.C++程序设计实践指导.北京:
清华大学出版社,2005
[3]马秀丽,刘志妩.C语言程序设计.北京:
清华大学出版社,2008
[4]刘振安,刘燕君.C++程序设计课程设计.北京:
清华大学出版社,2004忽略此处..