数据结构实验3----表达式求值问题

实验题目

实验题目:表达式求值问题。这里限定的表达式求值问题是: 用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果。

算术表达式求值过程是:

        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.运行结果和分析

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值