实验题目
实验题目:表达式求值问题。这里限定的表达式求值问题是: 用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果。
算术表达式求值过程是:
STEP 1:先将算术表达式转换成后缀表达式。
STEP 2:然后对该后缀表达式求值。
实验说明:在设计相关算法中用到栈,这里采用顺序栈存储结构。
中缀表达式exp ==》后缀表达式postexp伪代码如下:
初始化运算符栈op;
将'='进栈;
从exp读取字符ch;
while (ch!='\0')
{ if (ch不为运算符)
将后续的所有数字均依次存放到postexp中,并以字符'#'标志数值串结束;
else
switch(Precede(op栈顶运算符,ch))
{
case '<': //栈顶运算符优先级低
将ch进栈; 从exp读取下字符ch; break;
case '=': //只有栈顶运算符为'(',ch为')'的情况
退栈; 从exp读取下字符ch; break;
case '>': //栈顶运算符应先执行,所以出栈并存放到postexp中
退栈运算符并将其存放到postexp中; break;
}
}
若字符串exp扫描完毕,则将运算符栈op中'='之前的所有运算符依次出栈并存放到postexp中。最后得到后缀表达式postexp;
对后缀表达式postexp求值伪代码如下:
while (从postexp读取字符ch,ch!='\0')
{ 若ch为数字,将后续的所有数字构成一个整数存放到数值栈st中。
若ch为“+”,则从数值栈st中退栈两个运算数,相加后进栈st中。
若ch为“-”,则从数值栈st中退栈两个运算数,相减后进栈st中。
若ch为“*”,则从数值栈st中退栈两个运算数,相乘后进栈st中。
若ch为“/”,则从数值栈st中退栈两个运算数,相除后进栈st中(若除数为零,则提示相应的错误信息)。}
若字符串postexp扫描完毕,则数值栈op中的栈顶元素就是表达式的值。
实验内容
1.问题设计分析
为了将算术表达式转换成后缀表达式,然后对该后缀表达式求值。并且要求设计相关算法中用到栈,采用顺序栈存储结构。首先要声明一个字符串数组,然后通过循环将表达式输入,这里才用的是#为结束输入。因为最后的#也输入了进去,所以在结束输入前应将最后的#去掉,也就是最后的元素为空(NULL)。随后建立一个字符串数组postexp,通过trans函数储存exp的后缀表达式。而trans函数则是建立一个栈并初始化通过switch语句判定字符是否入栈还是出栈,最后再将栈中的元素出栈给postexp作为后缀表达式。然后再通过compvalue函数将后缀表达式进行求值,原理通trans函数一样。
2.程序编码
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct
{
ElemType data[MaxSize];
int top; //栈指针
} SqStack; //顺序栈类型
void InitStack(SqStack *&s) //初始化栈
{
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
}
void DestroyStack(SqStack *&s) //销毁栈
{
free(s);
}
bool StackEmpty(SqStack *s) //判断栈是否为空
{
return(s->top==-1);
}
bool Push(SqStack *&s,ElemType e) //元素e入栈
{
if (s->top==MaxSize-1) //栈满的情况,即栈上溢出
return false;
s->top++;
s->data[s->top]=e;
return true;
}
bool Pop(SqStack *&s,ElemType &e) //出栈
{
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top];
s->top--;
return true;
}
bool GetTop(SqStack *s,ElemType &e) //取栈顶元素
{
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top];
return true;
}
void trans(char * exp,char postexp[])
{
char e;
SqStack * Optr;
InitStack(Optr);
int i=0;
while (* exp!='\0')
{
switch(* exp)
{
case '(':
Push(Optr,'(');
exp++;
break;
case ')':
Pop(Optr,e);
while (e!='(')
{
postexp[i++]=e;
Pop(Optr,e);
}
exp++;
break;
case '+':
case '-':
while (!StackEmpty(Optr))
{
GetTop(Optr,e);
if(e!='(')
{
postexp[i++]=e;
Pop(Optr,e);
}
else
break;
}
Push(Optr,*exp);
exp++;
break;
case '*':
case '/':
while (!StackEmpty(Optr))
{
GetTop(Optr,e);
if(e=='*'||e=='/')
{
postexp[i++]=e;
Pop(Optr,e);
}
else
break;
}
Push(Optr,*exp);
exp++;
break;
default:
while(*exp>='0'&&*exp<='9')
{
postexp[i++]=*exp;
exp++;
}
postexp[i++]='#';
}
}
while (!StackEmpty(Optr))
{
Pop(Optr,e);
postexp[i++]=e;
}
postexp[i]='\0';
DestroyStack(Optr);
}
double compvalue(char * postexp)
{
ElemType d,a,b,c,e;
SqStack *Opnd;
InitStack(Opnd);
while (*postexp!='\0')
{
switch (*postexp)
{
case '+':
Pop(Opnd,a);
Pop(Opnd,b);
c=b+a;
Push(Opnd,c);
break;
case '-':
Pop(Opnd,a);
Pop(Opnd,b);
c=b-a;
Push(Opnd,c);
break;
case '*':
Pop(Opnd,a);
Pop(Opnd,b);
c=b*a;
Push(Opnd,c);
break;
case'/':
Pop(Opnd,a);
Pop(Opnd,b);
if(a!=0)
{
c=b/a;
Push(Opnd,c);
break;
}
else
{
printf("\n\t除零错误!\n");
exit(0);
}
break;
default:
d=0;
while(*postexp>='0'&& *postexp<='9')
{
d=10*d+*postexp-'0';
postexp++;
}
Push(Opnd,d);
break;
}
postexp++;
}
GetTop(Opnd,e);
DestroyStack(Opnd);
return e;
}
int main()
{
char exp[MaxSize];
printf("请输入表达式(#为结束):");
int i;
for(i=0;i<MaxSize;i++)
{
scanf("%c",&exp[i]);
if(exp[i]=='#')
{
exp[i]=NULL;
break;
}
}
char postexp[MaxSize];
trans(exp,postexp);
printf("中缀表达式:%s\n",exp);
printf("后缀表达式:%s\n",postexp);
printf("表达式的值:%g\n",compvalue(postexp));
return 1;
}
3.运行结果和分析