实验题目:栈的应用-算术表达式求值
实验目的 :
1.掌握栈的定义及实现;
2.掌握利用栈求解算术表达式的方法。
实验内容:
通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数要给出其实现过程:
(1) 函数In(c):判断c是否为运算符;
(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;
(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。
程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。如下图:
实验提示 :(仅供参考,每个函数的具体实现可以有多种方法,希望有创新)
1. 将栈的定义和实现单独保存在头文件“stack.h”中,然后在表达式求值的源程序中包含此头文件(即#include“stack.h”)。
2.表达式求值源程序的具体实现
(1) 主函数如下:
void main()
{
Printf(“请输入算术表达式,并以#结束.\n”);
Printf(“the result of expression is:%d\n”,EvaluateExpression());
}
(2) 函数EvaluateExpression的实现见算法3.22
(3) 函数In(c)的实现可以采用以下方式:
Status In(SElemType c)//应在前面有定义typedef char SElemType;
{ // 判断c是否为运算符
switch(c)
{
case'+':return TRUE;
……//补充完整
default:return FALSE;
}
}
(4) 函数Precede(t1,t2)的实现可以采用以下形式:
SElemType Precede(SElemType t1,SElemType t2)
{ //根据教材表3.1,判断两个运算符的优先关系
SElemType f;
switch(t2)
{
case '+':
case '-':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
……//补充完整
}
return f;
}
(5) 函数Operate(a,theta,b)的实现可以采用以下方式:
SElemType Operate(SElemType a,SElemType theta,SElemType b)
{
SElemType c;
a=a-48;
b=b-48;
switch(theta)
{
case'+':c=a+b+48;
break;
……//补充完整
}
return c;
}
选做内容:进一步改进,使表达式的中间值及最终结果不局限于0~9之间的个位数。(如果完成要在实验报告中注明),如下图:
实验要求 :
(1) 程序要添加适当的注释,程序的书写要采用缩进格式。
(2) 程序要具在一定的健壮性,即当输入数据非法时, 程序也能适当地做出反应。
(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。
(4) 根据实验报告模板详细书写实验报告,在实验报告中给出表达式求值算法的流程图。
#include
#include
#include
#include
#include
#include
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;
int In(char ch) // 判断输入字符是否为运算符
{
if(ch=='+') return OK;
if(ch=='-') return OK;
if(ch=='*') return OK;
if(ch=='/') return OK;
if(ch=='(') return OK;
if(ch==')') return OK;
if(ch=='#') return OVERFLOW;
return ERROR;
}
char Precede(char a,char b) // 比较符号 a与符号 b的优先级.如 a 优于 b,则返回 ' > ',否则返回 ' < ' 或 ' = '
{
if(b=='+')
{
if(a=='('||a=='#') return '<';
return '>';
}
if(b=='-')
{
if(a=='('||a=='#') return '<';
return '>';
}
if(b=='*')
{
if(a=='*'||a=='/'||a==')') return '>';
return '<';
}
if(b=='/')
{
if(a=='*'||a=='/'||a==')') return '>';
return '<';
}
if(b=='(') return '<';
if(b==')')
{
if(a=='(') return '=';
return '>';
}
if(b=='#')
{
if(a=='#') return '=';
return '>';
}
}
double Operate(double a,char theta,double b) // 把 a、b进行二元运算
{
if(theta=='+') return a+b;
if(theta=='-') return a-b;
if(theta=='*') return a*b;
if(theta=='/') return a/b;
}
double EvaluateExpression() // 计算过程
{
char str[10010];
stack OPND;
stack OPTR;
scanf("%s",str);
OPTR.push('#');
double a,b,shu=0;
int flag=0;
char theta;
for(int i=0;str[i];i++)
{
if(In(str[i])==0)
{
shu=shu*10+str[i]-'0';
flag=1;
}
else
{
if(flag)
{
OPND.push(shu);
shu=0;
flag=0;
}
switch(Precede(OPTR.top(),str[i]))
{
case '<':
OPTR.push(str[i]);
break;
case '>':
theta=OPTR.top(); OPTR.pop();
b=OPND.top(); OPND.pop();
a=OPND.top(); OPND.pop();
OPND.push(Operate(a,theta,b));
i--; // 这里是因为判断的该符号 str[i] 还没有入栈,故需要回去判断一下
break;
case '=':
OPTR.pop();
break;
}
}
}
return OPND.top();
}
int main()
{
printf("\n************************************************************************\n\n");
puts("温馨提醒:\n");
puts(" 为了方便,请您在输入表达式的结尾加一个符号 '#',以判断您的输入完成");
puts("\n 如若忘了输入结束字符 '#',结果可能有误");
printf("\n************************************************************************\n\n");
puts("\n请输入您想要计算的表达式:\n");
printf("\n计算结果为:%.2lf\n",EvaluateExpression());
puts("\n\n\n\n谢谢您的使用,请按任意键退出");
system("pause");
return 0;
}