表达式求值

//表达式求值基本思路:
//第一步:中缀表达式转后缀表达式即逆波兰表达式
/*规则: 从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后
        缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低
        于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直
        到最终输出后缀表达式为止。
*/
//第二步:进行逆波兰表达式求值
/*
规则:  从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符
       号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
*/
//详解见大话数据结构
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 30

typedef double ElemType;
typedef char ElemType1;
char str[MAXBUFFER];
char operation[MAXBUFFER];
int prior[50];
typedef struct  
{
	ElemType *base;
	ElemType *top;
	int stacksize;
}SqStack;

typedef struct  
{
	ElemType1 *base;
	ElemType1 *top;
	int stacksize;
}SqStack1;
SqStack s;
SqStack1 Symble;
InitStack(SqStack &S)
{
	S.base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
	if (!S.base)
	{
		exit(0);
	}
	S.top=S.base;
	S.stacksize=STACK_INIT_SIZE;
}

Push(SqStack &S,ElemType e)
{
	if (S.top-S.base>=S.stacksize)
	{
		S.base=(ElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType));
		if (!S.base)
		{
		   exit(0);
		}
		S.top=S.base+S.stacksize;
		S.stacksize+=STACKINCREMENT;
	}
	*S.top++=e;
}

int Pop(SqStack &S,ElemType &e)
{
	if (S.top==S.base)
	{
		return -1;
	}
	else
	{
		e=*(--S.top);
		return 0;
	}

}



InitStack1(SqStack1 &S)
{
	S.base=(ElemType1 *)malloc(STACK_INIT_SIZE*sizeof(ElemType1));
	if (!S.base)
	{
		exit(0);
	}
	S.top=S.base;
	S.stacksize=STACK_INIT_SIZE;
}

Push1(SqStack1 &S,ElemType1 e)
{
	if (S.top-S.base>=S.stacksize)
	{
		S.base=(ElemType1 *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType1));
		if (!S.base)
		{
		   exit(0);
		}
		S.top=S.base+S.stacksize;
		S.stacksize+=STACKINCREMENT;
	}
	*S.top++=e;
}

int Pop1(SqStack1 &S,ElemType1 &e)
{
	if (S.top==S.base)
	{
		return -1;
	}
	else
	{
		e=*(--S.top);
		return 0;
	}

}

char  GetTopElem1(SqStack1 S)
{
	if (S.top==S.base)
		return '\0';
	else
		return *(S.top-1);
}
void priorarray()  //优先级数组
{
	prior[0]=-1;  //空栈
	prior[40]=0;  //左括号
	prior[43]=1;  //加号
	prior[45]=1;  //减号
	prior[42]=2;  //乘号
	prior[47]=2;  //除号
}

int Prior(char str1,char str2) //获取优先级,
{
	if (prior[str1]>=prior[str2])
	{
		return 1;
	}
	else
		return 0;
}
void MidToBack(char* operation) //中缀表达式转后缀表达式
{
	int i=0;
	char e;
	while(*operation!='\0')
	{
		if(isdigit(*operation)||*operation=='.')//如果是数字就输出
		{
			str[i++]=*operation;
			if (!isdigit(*(operation+1))&&*(operation+1)!='.')
			{
				str[i++]=' ';//数字和数字,数字和运算符之间用空格隔离,便于解析
			}
		}
		else //否则进行栈操作
		{
			
			switch(*operation)
			{
			case '-':
			case '+':
			case '*':
			case '/':
					if(Prior(*operation,GetTopElem1(Symble)))//如果优先级高于栈顶元素
					{
						Push1(Symble,*operation); //则入栈
					}
					else   
					{
						while (GetTopElem1(Symble)!='('&&GetTopElem1(Symble)!=0)
						{
							Pop1(Symble,e); //如果低于栈顶元素,则栈顶元素依次出栈,知道栈为空,或栈顶元素为左括号
							str[i++]=e;
						}
					
						Push1(Symble,*operation);//将本次运算符进栈
					}
					break;
			case '(':   //直接进栈
					Push1(Symble,*operation);
					break;
			case ')':  //消括号
				    while (GetTopElem1(Symble)!='(')
					{
						Pop1(Symble,e);
						str[i++]=e;
					}
					Pop1(Symble,e);
					break;
					
			}
		}
		operation++;
	}
	while (GetTopElem1(Symble)!=0) //栈顶元素全部出栈
	{
		Pop1(Symble,e);
		str[i++]=e;
	}
	str[i]='\0';
}

int Cal(char *operation,double *final) //逆波兰表达式求值
{
	char temp[11];
	int i=0;
	double d,e;
	while (*operation!='\0')
	{
		if(isdigit(*operation)||*operation=='.')
		{
			temp[i++]=*operation;
		
			if (i>=10)
			{
				printf("出错:输入的单个数据过大!\n");
				exit(1);

			}
		
		
		}
		else if (*operation==' ') //字符串转浮点
		{
			temp[i]='\0';
			d=atof(temp);
			Push(s,d);
			i=0;
				
		}
		else
		switch(*operation) 
		{
		case '+':
			Pop(s,e);
			Pop(s,d);
			Push(s,d+e);
			break;
		case '-':
			Pop(s,e);
			Pop(s,d);
			Push(s,d-e);
			break;
		case '*':
			Pop(s,e);
			Pop(s,d);
			Push(s,d*e);
			break;
		case '/':
			Pop(s,e);
			Pop(s,d);
			if (e!=0)
			{
				Push(s,d/e);
			}
			else
			{
				printf("\n出错:除数为零!\n");
				return -1;
			}
			break;
		}
		operation++;
	}
	Pop(s,d);
	*final=d;
}
int main()
{
	double final;
	InitStack1(Symble); //初始化运算符栈
	InitStack(s); //初始化数字栈
	printf("请输入表达式\n");
	scanf("%s",operation);
	priorarray(); //初始化优先级数组
	MidToBack(operation); //调用中转后
	Cal(str,&final);//逆波兰求值
	printf("\n最终的计算结果为:%f\n",final);
	return 0;
}
<img src="https://img-blog.csdn.net/20140903112457414?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3VuMTk5MTAxMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值