C语言实现中缀表达式求值

中缀转后缀
	#include <stdio.h>		
	#include <ctype.h>	//提供isalpha原型 
	
	/*比较运算符a、b的优先级 */ 
	int Priority(char a, char b){
		switch(a){
			case '*':
			case '/': 
				return 1;		//a>b
				break;
	
			case '+':
			case '-': 
				if(b=='+' || b=='-')
					return 1;	//a>b
			  	else
			  		return 0;	//a<b
		  		break; 
		}
	}
	
	
	/* 中缀式变后缀式(带括号) */
	/* 逆波兰式:即后缀表达式,将运算符写在操作数之后 */
	/* 如"(a+b*c)/d-e"将转化为:"abc*+d/e-" */
	/* 假设表达式变量为单字母,操作符有'+'、'-'、'*'、'/'、'('、')' */
	/*
	转换规则
	1、如果遇到操作数,我们就直接将其存入暂存逆波兰式的数组c
	2、如果遇到左括号,我们也将其直接放入栈中
	3、如果遇到右括号,则将栈元素弹出存入数组c,直到遇到左括号为止。注意:【左括号只弹出并不存入数组c】
	4、如果遇到运算符,如:“+”,“-” “*”,“/”
	   (1)若栈中运算符优先级高,将栈中优先级高的运算符弹出并送入数组c,直到出现情况(2)为止
	   (2)若栈中运算符优先级低或栈为空,将读取到的字符压入栈	
	   (3)有一点需要注意,只有在遇到")"的情况下我们才弹出"(",其他情况我们都不会弹出"("
	5、如果读到了中缀式的末尾,则将栈中所有元素依次弹出存入数组c
	6、最终后缀表达式就存储在了数组c中,将其输入即可
	*/
	void Algo_1(char *s, char c[]){ //用一个足够大的数组暂存逆波兰式				
		int i, j; 
		char e;	  //char和int类型可直接比较 
		char stack[100]; //栈中临时存储操作符 
		int top=-1;
		
		i = j = 0;
		
		while(s[i]!='\0'){ //如果还没有读到中缀式的末尾
			if(isalpha(s[i]))	//读到单字母
				c[j++] = s[i];	//字母直接送入数组 
			else if(s[i]=='('){
				stack[++top]=s[i]; //如果遇到左括号,将其入栈	
			}
			else if(s[i]==')'){ //如果遇到右括号,将栈中元素出栈并送入数组,直到遇到左括号
				while(stack[top]!='('){
					e=stack[top--];	 
					c[j++] = e;
				}
				stack[top--]; //将左括号出栈,不加入数组【后缀表达式不包含左右括号】
			}
			else{               //读到的是运算符 
				while(top!=-1){
					e=stack[top]; //获取栈顶元素
	
					/*
					注意栈中也会存储左括号,因此获取的栈顶元素可能是左括号
					由于左括号优先级小于+、-、*、/,因此碰到'('时不用出栈,直接break即可
					*/
					if(e!='('&&Priority(e, s[i])){  //栈中运算符优先级高【这里的运算符只包含+、-、*、/】
						e=stack[top--];	 //将栈中优先级高的运算符送入数组 
						c[j++] = e;
					}
					else	//遇到栈中运算符优先级低时,结束循环 
						break;	
				}	
		        
				stack[++top]=s[i]; //将读取到的优先级高的字符压入栈	
			}
			
			i++;	//继续读取 
		}
		
		while(top!=-1){
			e=stack[top--];	 //出栈 
			c[j++] = e;		
		}
		
		c[j] = '\0';  //数组中转换后的逆波兰式以"\0"标记结束 
	}
	
	int main(int argc, char *argv[]){
		char *s = "(a+b*c)/d-e";
		char c[100];
		
		printf("中缀表达式为:");
		printf("%s\n",s);
		printf("\n");
			
		Algo_1(s, c);
		printf("生成的后缀表达式:");
		printf("%s\n",c);
		printf("\n");
		
		return 0;
	}
后缀表达式求值
	#include <stdio.h>		
	#include <ctype.h>	//提供isdigit原型 
	
	/*
	后缀表达式具有和前缀表达式类似的好处,没有优先级的问题【无括号】
	1、直接读取表达式,如果遇到数字就压栈
	2、如果遇到运算符,就弹出两个数进行运算,随后再将运算结果压栈
	*/
	
	/* 计算a<oper>b */
	char Operate(char a, char oper, char b){
		char c;
		
		switch(oper){
			case '+': c = (a-48)+(b-48)+48;
				break;
			case '-': c = (a-48)-(b-48)+48;
				break;
			case '*': c = (a-48)*(b-48)+48;
				break;
			case '/': c = (a-48)/(b-48)+48;
				break;
		}
		
		return c;
	}
	
	
	/* 对逆波兰表达式求值 */
	/*预设操作符为'+','-','*','/',变量为单数字 */
	int Algo_2(char c[], char *Value){
		int i=0;
		int top=-1;  //栈顶指针
		int stack[100];  //设栈的容量为00
		char a, b;
		
		while(c[i]){		
			if(isdigit(c[i]))		//遇到数字
				stack[++top]=c[i];
			else{
				b=stack[top--];
				a=stack[top--];	   //先弹出来的在操作数后边 
				stack[++top]=Operate(a, c[i], b);
			}
			i++;		 
		} 
		
		*Value=stack[top--];
	
		if(top!=-1) //栈不为空时
			return 0;
		else
			return 1;
	}
	
	int main(int argc, char *argv[]){
		/*中缀表达式:(a+b*c)/d-e【(3+3*4)/3-2】  
		后缀表达式:abc*+d/e-【334*+3/2-】*/
		char c[] = "334*+3/2-";  
		char value;
		
		printf("已知逆波兰式为:");
		printf("%s\n", c);
		Algo_2(c, &value);
		printf("逆波兰式的计算结果为:%d\n", value-48);
		printf("\n");
		
		return 0;
	}
  • 0
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值