2471 表达式的转换

来源:互联网 发布:手机淘宝评价管理 编辑:程序博客网 时间:2024/06/06 02:58
题目描述 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
该文将了四则运算优先级的定义

0 0
原创粉丝点击