四则运算符表达式求值

四则运算符表达式求值

中缀表达式转后缀表达式(栈用来存放运算符号)

从左到右遍历中缀表达式中的每个数字和符号,若是数字就输出,成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,如果是有括号或者该符号低于栈顶符号(乘除优先加减),则栈顶元素依此出栈并输出,并将该符号进栈,一直到最后得到后缀表达式。

后缀表达式求值(栈用来存放运算数)

从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶两个数字出栈,运算后结果进栈,一直到得出结果。

/************************************************************************
*设计一个算法,将一般算术表达式转化为逆波兰表达式,并求逆波兰表达式的值。
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_SIZE	100
//------------类型声明及变量定义------------------
int opndStack[MAX_SIZE];//运算对象栈
int opndTop;//运算对象栈顶指针
char optrStack[MAX_SIZE];//运算符栈
int optrTop;//运算符栈顶指针
struct optrNode//运算符结点结构
{
	char optr;//运算符
	int level;//优先级别,值大级别高
};
struct optrNode	optrTable[7]={'(',5,')',5,'*',4,'/',4,'+',2,'-',2,'#',0};//运算符优先级表,{运算符,级别,运算符,级别~~ } 

//以字符串的形式获取中缀表达式
void getInfixExpression(char str[])
{
	int len;
	while(1)//循环直到输入了正确的中缀表达式
	{	
		printf("请输入表达式(中缀),以#结束:");
		fflush(stdin);
		gets(str);
		len=strlen(str);
		if(str[0]=='#')//表达式第1位是#
		{
			printf("表达式不要以#开头,请重新输入!\n");
			continue;
		}
		if(str[len-1]!='#')//表达式不是以#结束
		{
			printf("表达式必须以#结束,请重新输入!\n");
			continue;
		}
		break;//表达式输入符合规范,中止循环
	}
	return;	
}
//栈初始化,运算对象栈为空,运算符栈为'#'
void initStack(void)
{
	opndTop=-1;
	optrTop=0;
	optrStack[optrTop]='#';
	return;
}
//运算对象入栈
void pushOpnd(int opnd)
{
	if(opndTop==MAX_SIZE-1)//栈满
	{
		printf("错误:栈满!\n");
		return;
	}
	opndTop++;
	opndStack[opndTop]=opnd;
	return;
}
//运算符入栈
void pushOptr(char optr)
{
	if(optrTop==MAX_SIZE-1)//栈满
	{
		printf("错误:栈满!\n");
		return;
	}
	optrTop++;
	optrStack[optrTop]=optr;
	return;
}
//运算对象出栈,成功返回1,*opnd存放出栈元素,否则返回0
int popOpnd(int *opnd)
{
	if(opndTop==-1)
	{
		printf("错误:栈空!\n");
		return 0;
	}
	*opnd=opndStack[opndTop];//栈顶元素出栈
	opndTop--;
	return 1;
}
//运算符出栈,成功返回1,*optr存放出栈元素,否则返回0
int popOptr(char *optr)
{
	if(optrTop==-1)
	{
		printf("错误:栈空!\n");
		return 0;
	}
	*optr=optrStack[optrTop];//栈顶元素出栈
	optrTop--;
	return 1;
}
//获得栈顶运算符
char getTopOptr(void)
{
	if(optrTop!=-1)
		return optrStack[optrTop];//返回栈顶运算符
	else
		return 0;//返回空
}
//运算符优先级别比较, a>b,返回1, a==b,返回0, a<b,返回-1
int optrCompare(char optrA,char optrB)
{
	int i,levelA,levelB;
	for(i=0;i<7;i++)//总共7个运算符,查找optrA的优先级别
	{
		if(optrTable[i].optr==optrA)
		{
			levelA=optrTable[i].level;
			break;
		}
	}
	for(i=0;i<7;i++)//总共7个运算符,查找optrB的优先级别
	{
		if(optrTable[i].optr==optrB)
		{
			levelB=optrTable[i].level;
			break;
		}
	}
	if(levelA>levelB)
		return 1;
	else if(levelA==levelB)
		return 0;
	else
		return -1;
}
//将数字符与数值n合并转换为整数并返回
int charCombineToInt(int n,char c)
{
	int v;
	v=c-48;//将数字字符转换为数值
	n=n*10+v;//接接到n中
	return n;//返回
}
//中缀表达式转换为后缀表达式
void InfixExpressionToSuffixExpression(char infixExpression[],char suffixExpression[])
{
	int i,j,si;
	char ch,optr;
	initStack();//初始化栈
	i=0;
	si=0;//后缀表达式下标
	while((ch=infixExpression[i])!='\0')//未处理完循环
	{
		if(ch>='0' && ch<='9')//是数字字符
		{
			j=i+1;
			suffixExpression[si]=ch;//结果
			si++;
			while(infixExpression[j]>='0' && infixExpression[j]<='9')  //先把数字放在前面 
			{
				suffixExpression[si]=infixExpression[j];
				j++;//继续判断下一字符
				i++;//标识当前字符已处理完
				si++;
			}
			suffixExpression[si]=32;//以空格隔开
			i++;//继续处理下一个字符
			si++;
		}
		else//运算符
		{
			char topOptr;//当前栈顶运算符
			topOptr=getTopOptr();
			if(topOptr=='#' && ch=='#')//#匹配,转换结束
			{
				break;//转换结束
			}
			else if(topOptr!='#' && ch=='#')//当前运算符是#,栈顶运算符不是'#'
			{
				popOptr(&optr);//运算符出栈
				suffixExpression[si]=optr;
				si++;
				suffixExpression[si]=32;//空格
				si++;
			}
			else if(ch==')' && topOptr!='(')//当前运算符是右括号')',且栈顶运算符不是左括号'('
			{
				popOptr(&optr);//运算符出栈
				suffixExpression[si]=optr;
				si++;
				suffixExpression[si]=32;//空格
				si++;
			}
			else if(topOptr=='(' && ch!=')')//如果栈顶运算符是左括号'('且当前运算符不是右括号')',则运算符入栈
			{
				pushOptr(ch);//运算符入栈
				i++;//继续处理下一个字符
			}
			else if(topOptr=='(' && ch==')')//如果栈顶运算符是左括号'('且当前运算符是右括号')',则运算符出栈,继续处理一下字符
			{
				popOptr(&optr);//运算符出栈
				i++;//继续处理下一个字符
			}
			else if(optrCompare(ch,topOptr)==1)//当前运算符比栈顶运算符优先级别高
			{
				pushOptr(ch);//运算符入栈
				i++;//继续处理下一个字符
			}
			else if(optrCompare(ch,topOptr)==-1)//当前运算符比栈顶运算符优先级别低
			{
				popOptr(&optr);//运算符出栈
				suffixExpression[si]=optr;
				si++;
				suffixExpression[si]=32;//空格
				si++;
			}
			else if(optrCompare(ch,topOptr)==0)//运算符优先级别相等,从左到右按先后次序计算
			{
				popOptr(&optr);//运算符出栈
				suffixExpression[si]=optr;
				si++;
				suffixExpression[si]=32;//空格
				si++;
			}
		}
	}
	suffixExpression[si]='\0';//表达式结束
	return;
}
//opnd出栈两个运算对象,执行optr运算,结果入opnd栈
void calculate(char optr)
{
	int a,b,result;
	popOpnd(&a);//出栈一个运算对象
	popOpnd(&b);//再出栈一个运算对象
	switch(optr)
	{
	case '*': result=a*b; break;
	case '/': result=b/a; break;
	case '+': result=a+b; break;
	case '-': result=b-a; break;
	}
	pushOpnd(result);//运算结果入栈
	return;
}
//后缀表达式求值
void calculateSuffixExpression(char suffixExpression[])
{
	int i,j,ret,value;
	char ch;
	initStack();//初始化栈
	i=0;
	while((ch=suffixExpression[i])!='\0')//逐一处理表达式的每个字符
	{
		if(ch>='0' && ch<='9')//是数字字符
		{
			j=i+1;
			value=ch-48;
			while(suffixExpression[j]>='0' && suffixExpression[j]<='9')
			{
				value=charCombineToInt(value,suffixExpression[j]);
				j++;//继续判断下一字符
				i++;//标识当前字符已处理完
			}
			pushOpnd(value);//运算对象入栈;
			i++;//继续处理下一个字符
		}
		else if(ch==32)//是空格,忽略
			i++;
		else//是运算符,从opndStack出栈两个运算对象,执行运算并将结果入栈
		{	
			calculate(ch);
			i++;
		}
	}//逐一处理表达式的每个字符
	ret=popOpnd(&value);//运算结果出栈
	printf("%d\n",value);
	return;
}
int main()
{
	char ch,infixExpression[MAX_SIZE];//要转换的中缀表达式
	char suffixExpression[MAX_SIZE];//转换后的后缀表达式(逆波兰式)
	int i;
	while(1)
	{
		getInfixExpression(infixExpression);//获取要转换的中缀表达式
		InfixExpressionToSuffixExpression(infixExpression,suffixExpression);//中缀表达式转换为后缀表达式
		printf("后缀表达式(逆波兰式)是:");
		i=0;
		while(suffixExpression[i]!='\0')
		{
			printf("%c",suffixExpression[i]);
			i++;
		}
		printf("\n该后缀表达式的值是:");
		calculateSuffixExpression(suffixExpression);//计算后缀表达的值并输出
		fflush(stdin);
		printf("继续转换并计算下一个表达?(Y/N):");
		ch=getchar();
		if(ch=='Y' || ch=='y')//Yes
			continue;
		else
			break;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值