2471 表达式的转换

题目描述 Description

平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而中缀表达式就不必用括号了。

后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。

例如:8(3+2*6)/5+4可以写为:8 3 2 6*+5/4+

其计算步骤为:8  3   2  6  *  +  5  /  –  4  + 

              8  3  12  +  5  /  –  4  + 

              8  15  5  /  –  4  + 

              8  3  –  4  + 

              5  4  + 

              9

   编写一个程序,完成这个转换,要求输出的每一个数据间都留一个空格。

输入描述 Input Description

就一行,是一个后缀表达式。输入的符号中只有这些基本符号“0123456789+-*/^()”,并且不会出现形如2*-3的格式。

表达式中的基本数字也都是一位的,不会出现形如12形式的数字。

所输入的字符串不要判错。

输出描述 Output Description

   若干个中缀表达式,第I+1行比第I行少一个运算符和一个操作数,最后一行只有一个数字,表示运算结果。

    运算的结果可能为负数,“/”以整除运算。

样例输入 Sample Input

8(3+2*6)/5+4

样例输出 Sample Output

8  3   2  6  *  +  5  /  –  4  + 

8  3  12  +  5  /  –  4  + 

8  15  5  /  –  4  + 

8  3  –  4  + 

5  4  + 

9


分析:通过这个题目练习了编译原理的一些内容。包括递归下降算法,左递归的消除,语法制导翻译的少部分内容。

通过递归下降转换为后缀式,然后通过后缀式的计算方法来计算表达式,每次计算出一个结果将整个后缀式输出一次。

题目中要求的表达式消除左递归后为。


E->T1E1

E1->+T1E1 | -T1E1

T1->T2T11

T11->*T2T11 |  /T2T11

T2->T3T22

T22->^T3T22

T3->(E) | i             

然后编码就很容易了,代码如下。应为这个题目保证输入都正确,因此没进行出错的提示。

#include <iostream>
#include <list>
#include <string>
#include <cmath>
using namespace std;
string str; //句子
int i = 0;  //读入字符的位置

list<char> postFix;

void T();
void E1();
void T1();
void T11();
void T2();
void T22();
void T3();
void G();
void F();
void S();

void E()
{
	T1();
	E1();
}

void E1()
{
	if(i < str.size() && (str[i] == '+' || str[i] == '-'))
	{
		int ti = i;
		i++;
		T1();
		if (str[ti] == '+')
		{
			postFix.push_back('+');
		}
		else
		{
			postFix.push_back('-');
		}
		E1();
	}
}

void T1()
{
	T2();
	T11();
}

void T11()
{
	if(i < str.size() && (str[i] == '*' || str[i] == '/'))
	{
		int ti = i;
		i++;
		T2();
		if(str[ti] == '*')
		{
			postFix.push_back('*');
		}
		else if(str[ti] == '/')
		{
			postFix.push_back('/');
		}
		T11();
	}
}

void T2()
{
	T3();
	T22();
}

void T22()
{
	if (i < str.size() && str[i] == '^')
	{
		i++;
		T3();
		postFix.push_back('^');
		T22();
	}
}

void T3()  // 终结符 或 ()
{
	if(isalnum(str[i]))
	{
		postFix.push_back(str[i]);
		i++;
		
	}
	else if(str[i] == '(')
	{
		    i++;
			E();
			if(str[i] == ')')
			{
				i++;
			}
	}
}

void print(list<int> &operand)
{
	list<int>::iterator it;
	for (list<int>::iterator it = operand.begin(); it != operand.end(); ++it)
	{
		cout<<*it<<" ";
	}
	for (list<char>::iterator it = postFix.begin(); it != postFix.end(); ++it)
	{
		cout<<*it<<" ";
	}
    cout<<endl;
}

void cal() // 表达式是自左向右结合
{
	list<int> operand;
	print(operand);
	for (;postFix.size() > 0;)
	{
		if (isalnum(postFix.front()))
		{
			operand.push_back(postFix.front() -  '0');
			postFix.pop_front();
		}
		else
		{
			char c = postFix.front();
			postFix.pop_front();
			int n1 = operand.back();
			operand.pop_back();
			int n2 = operand.back();
			operand.pop_back();
			switch(c)
			{
				case '-':
					operand.push_back(n2-n1);
					break;
				case '+':
					operand.push_back(n2+n1);
					break;
				case '*':
					operand.push_back(n2*n1);
					break;
				case '/':
					operand.push_back(n2/n1);
					break;
				case '^':
					operand.push_back((int)pow(n2*1.0,n1*1.0));
					break;
			}
			print(operand);
		}
	}
}

int main()
{
	cin >> str;
	E();
	cal();
	return 0;
}

一些参考资料:

[1]http://wenku.baidu.com/view/2ae7e28fcc22bcd126ff0c08.html
编译原理6-4.2-4.3- 自顶向下翻译-递归下降翻译
[2]http://blog.sina.com.cn/s/blog_687911280100nc8t.html 
左递归消除。
[3]http://wenku.baidu.com/view/c3c9255f804d2b160b4ec0e7.html?re=view
递归下降翻译
[4]http://wenku.baidu.com/view/cb7d67631ed9ad51f01df254.html?re=view
第六章 属性文法和语法制导翻译
[5]http://blog.csdn.net/chosen0ne/article/category/1247484
该文将了四则运算优先级的定义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值