编译原理(中间代码生成)-逆波兰表示(后缀表达式)

18 篇文章 2 订阅
2 篇文章 0 订阅

1.需求

1、编制一个中间代码生成程序,能将算术表达式等翻译成逆波兰形式, 即从中缀表达式转换成后缀表达式
2、程序具有通用性,即能接受各种不同的算术表达式等语法成分。
3、对于语法正确的算术表达式,能生成逆波兰表示,并输出结果;

1+2, 是中缀表达式. 后缀表达式即运算符在后面的表达式.
逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式,下面是一些具体的例子:
正常的表达式 逆波兰表达式
a+b —> a,b,+
a+(b-c) —> a,b,c,-,+
a+(b-c)d —> a,b,c,-,d,,+
a+d*(b-c)—>a,d,b,c,-,*,+
a=1+3 —> a=1,3 +

2.算法

从左到右遍历中缀表达式:
1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素(即除了 ’ ( ',然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。

流程图:
举例:a+b * c+(d * e+f)* g ———> abc+de * f+g*+

遇到a,直接输出:在这里插入图片描述
遇到+,此时栈为空,入栈:
在这里插入图片描述
遇到b,直接输出:
在这里插入图片描述
遇到*,优先级大于栈顶符号优先级,入栈; 遇到c, 直接输出:
在这里插入图片描述
遇到+, 栈内的符号优先级都大于等于它, 所以先弹出栈内的符号, 再i压入+:
在这里插入图片描述

遇到(,将其入栈:
在这里插入图片描述

遇到d,直接输出:
在这里插入图片描述
遇到*,由于的优先级高于处在栈中的(,因此入栈:
在这里插入图片描述
遇到e,直接输出:
在这里插入图片描述
遇到+,栈顶*的优先级高于+,但是栈内的(低于+,将栈顶输出,+入栈:
在这里插入图片描述
遇到f,直接输出:
在这里插入图片描述

遇到),弹出栈顶元素并且输出(上面算法第4条),直到弹出(才结束,在这里也就是弹出+输出,弹出(但不输出:
在这里插入图片描述

遇到*,优先级高于栈顶+,将*入栈:
在这里插入图片描述

遇到g,直接输出:
在这里插入图片描述

此时已经没有新的字符了,依次出栈并输出操作直到栈为空:
在这里插入图片描述

将中缀表达式转换成后缀表达式的算法如下图所示:
在这里插入图片描述
转换为后缀表达式之后,对逆波兰表达式的计算:
在这里插入图片描述

3.代码

#include<bits/stdc++.h>
using namespace std;

char st[1000]; //保存符号的堆栈数组(模拟栈)
int top = -1; //堆栈指针
string ss = ""; //保存结果逆波兰式

int main(){
	printf("%s", "Input:");
	string s;
	
	cin>>s;
	int L = s.length();
	for(int i =  0;i < L; ++i){
		if(s[i]=='+'||s[i]=='-'){
			if(top==-1){ //栈为空, 遇到运算符,入栈
				st[++top] = s[i]; //将+,-入栈
			}else
			{
				while (st[top]!='(' && top > -1) //遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素(即除了 ' ( '
				{
					ss.push_back(st[top]);
					top--;
				}
				st[++top] = s[i]; //然后将该运算符入栈
			}
		}else if(s[i]=='*'||s[i]=='/'){
			if(top==-1){ //栈为空, 遇到运算符,入栈
				st[++top] = s[i]; //入符号栈
			}else{
				while (st[top]!='('&&(st[top]=='*'||st[top]=='/')) //同L20处, 不过st[top]不能为=或-,否则无法输出
				{
					ss.push_back(st[top]);
					top--;
				}
				st[++top] = s[i]; 
			}
		}else if(s[i]==')'){ //遇到右括号将左括号之前全部入栈,加入逆波兰式
			while(st[top]!='('){ //遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出
				ss.push_back(st[top]);
				top--;
			}
			top--; //左括号出栈但不加入逆波兰式
		}else{ 
			ss.push_back(s[i]); //操作数直接加入逆波兰式
		}
	} 

	//最后将堆栈中全部元素加入波兰式
	while(top>-1){
		ss.push_back(st[top]);
		top--;
	}
	printf("%s","逆波兰式为: ");
	cout<<ss<<endl;
	return 0;
} 

输入Input:2+3*5

输出:逆波兰式为: 235*+

  • 23
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值