用堆栈实现表达式的求解.docx
《用堆栈实现表达式的求解.docx》由会员分享,可在线阅读,更多相关《用堆栈实现表达式的求解.docx(10页珍藏版)》请在冰豆网上搜索。
用堆栈实现表达式的求解
题目二:
堆栈的应用
内容:
利用堆栈实现求算式表达式,表达式只包括4钟算术运算。
要求:
完成实验内容要求,编写程序实现。
用10组数据去测试,10组数据当中包括5组非法数据和5组合法数据。
提交报告,报告分三部分内容:
1)自己是怎么做的?
遇到什么问题,怎样解决的?
2)用了哪些数据,得到什么结果?
程序结果是不是跟你想的一样?
为什么不一样?
3)还有哪些值得改进或者不懂的?
解:
本次实验的部分代码主要参考了教材附带光盘里面的ALG00304部分,以实现更快的设计出可行的算法。
基本的设计思想如下:
为了实现算符的优先次序,设计了两个工作栈,一个为OPTR,用以寄存运算符;而另外一个为OPND,用来寄存操作数或运算结果。
首先设置操作数栈OPND为空栈,表达式起始符“#”为运算符栈的栈底元素。
依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕,即OPTR栈的栈顶元素和当前读入的字符均为“#”,其中#是结束符。
另外在此次的算法设计中还调用了两个库里面的函数,一个是Precede,主要是用来判定运算符栈的栈顶运算符与读入的运算符之间的优先关系的函数,另一个是Operate,为进行二元运算的函数,如果是编译表达式,则产生这个运算的一组相应指令并返回存放结果的中间变量,如果是解释执行表达式,则直接进行该运算,并返回运算的结果。
步骤:
先判断进栈符号的优先次序,如果是在合法符号之外的字符,定义为非法字符。
intfuhao(chard)//判断c是否为七种运算符之一。
接着设计算符表达式的优先算法,定义了两个栈OPTR和OPND,分别用来记录运算符和操作数,此外还用到了C语言中的一个函数atof将字符串转换成一个双精度数值并返回结果,C语言中的atof函数的形参是指针类型。
主函数为:
voidmain()
{
SElemTyperesult;
cout<<"请输入表达式,以#号结束"<//printf("请输入表达式,以#号结束:
\n");
result=EvaluateExpression();
//printf("所求的表达式的结果为:
\n",result);
cout<<"所求表达式的结果为:
"<}
而对于符号优先次序的判断,则设计了以下程序:
charPrecede(chara1,chara2)//判定运算符的优先级。
{charr;
switch(a2)
{
case'+':
case'-':
if(a1=='('||a1=='#')
r='<';
else
r='>';
break;
case'*':
case'/':
if(a1=='*'||a1=='/'||a1==')')
r='>';
else
r='<';
break;
case'(':
if(a1==')')
{
cout<<"括号匹配错误!
"<exit(OVERFLOW);
}
else
r='<';
break;
case')':
if(a1=='(')
r='=';
elseif(a1=='#')
{
cout<<"error!
没有左括号"<exit(OVERFLOW);
}
else
r='>';
break;
case'#':
switch(a1)
{
case'#':
r='=';
break;
case'(':
cout<<"error!
没有右括号"<exit(OVERFLOW);
default:
r='>';
}//switch
break;
}//switch
returnr;
}//Precede
如果输入的符号是在这7中之外的,我们定义为非法数据
intfuhao(chard)//判断c是否为七种运算符之一
{
switch(d)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
returnOK;
default:
returnERROR;
}//switch
}
SElemTypeOperate(SElemTypea,SElemTypetheta,SElemTypeb)//Operate为进行二元运算的athetab的函数
{
charn=theta;//此处把double型强制转换成int型,虽然会造成精度缺失,但本身theta是一个符号,也算是整型
switch(n)//转换后相当于和符号匹配ACSII码
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
default:
if(b!
=0)
returna/b;
else
{
cout<<"error!
除数不能为零"<exit(OVERFLOW);
}
}//switch
}
这里就是优先算法的实现部分,大部分是根据课本上的算法来进行设计的。
SElemTypeEvaluateExpression()//算符表达式的优先算法。
{
SqStackOPTR,OPND;//设OPTR和OPND分别为运算符栈和运算数栈
charc;
charData[11];//定义此数组为了存放整数或小数
SElemTypea,b,d,e;
InitStack(OPTR);//构造一个运算符栈
InitStack(OPND);//构造一个运算数栈
Push(OPTR,'#');//将#压入栈底
c=getchar();
GetTop(OPTR,e);
while(c!
='#'||e!
='#')//栈顶不是#号且输入不是#号
{
if(fuhao(c))//是符号则进栈
{
switch(Precede(e,c))
{
case'<':
//栈顶元素优先级低
Push(OPTR,c);
c=getchar();
break;
case'=':
//脱括号并接受下一字符
Pop(OPTR,e);
c=getchar();
break;
case'>':
//退栈并将运算结果入栈
Pop(OPTR,e);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,e,b));
break;
}//switch
}
elseif(c>='0'&&c<='9'||c=='.')//这里数字用字符表示表示相应的ACSII码
{
inti=0;
while(c>='0'&&c<='9'||c=='.')
{
Data[i]=c;
i++;
c=getchar();
}
Data[i]='\0';//数字没有存满,输入字符串结束符
d=atof(Data);//此处是利用C语言中的atof函数将字符串转换成一个双精度数值并返回结果,C语言中的atof函数的形参是指针类型,故用数组名
Push(OPND,d);
}
else
{
cout<<"error!
输入错误!
"<exit(OVERFLOW);
}
GetTop(OPTR,e);
}//while
GetTop(OPND,e);
returne;
}//EvaluateExpression
二:
10组运行结果截图如下(其中有5个是合法的,5个是非法的):
非法的用了诸如空格,美元符号,百分号,井号,不配对的括号等,出现的结果都是提示ERROR,输入错误。
5组合法数据:
5组非法数据:
三:
期待改进的地方
1.当表达式的第一位出现基本运算符+,-,*,/时,而且后面的全部都是合法数据,此时的结果是出现非正的浮点数,而不是提示出错,这个问题还没有解决。
2.当输入的值如果是26个英文字母是,是否可以将其转换成相对应的ASCII码进行正常的运算。