本篇是介绍的是后缀表达式最难,也是最基本的一个问题。即如何将一个中缀表达式转化为后缀表达式。在网上可以找到许多非递归实现的示例代码,它们比本节介绍的代码要简洁且高效,可是不利于理解。本节舍近求远,介绍后缀表达式的递归实现方式,为的是把变换的中心思想解释清楚。
问题描述
输入: 是一串字符串,它表示的是包含加减乘除四则运算以及括号运算的中缀表达式。为了简单起见,我们假设表达式中的运算元都是0到9之间的正整数。这样可以规避词法分析的细节。i
输出 的是一个Element对象组成的数组,表示一个后缀表达式。
主要思想
我们将运算根据优先级分成三组
具体实现
expr方法,代码如下
void expr(char* s, int & sn, Element* eles, int& en)
{
term(s, sn, eles, en);
while(s[sn] == '+' || s[sn] == '-')
{
int op = s[sn++];
term(s, sn, eles, en);
eles[en].is_op = true;
eles[en++].val = op;
}
}
代码的第一行首先调用term方法。这里term()函数的作用是处理最外层非加法和减法运算的表达式。可分为如下三种情况考虑。
term()函数定义与expr()函数完全类似。
void term(char* s, int & sn, Element* eles, int& en)
{
factor(s, sn, eles, en);
while(s[sn] == '*' || s[sn] == '/')
{
int op = s[sn++];
factor(s, sn, eles, en);
eles[en].is_op = true;
eles[en++].val = op;
}
}
1. 简单的数字;2. 带括号的表达式。
因此在factor()函数的定义中,也分为这两者情况讨论。
void factor(char* s, int & sn, Element* eles, int& en)
{
int op = s[sn++];
if(op == '(')
{
expr(s, sn, eles, en);
sn++;
}
else
{
eles[en].is_op = false;
eles[en++].val = op - '0';
}
}
代码第4-8行处理的是带括号的情形,而代码的第9-13行处理的是普通数字的情形。注意代码第7行,sn++的目的是把右圆括号pass掉。当然,我们这样处理,其实是假设用户输入的中缀表达式总是正确的。
最后附上完整的可执行代码。
#include
typedef struct str_ele{
bool is_op;
int val;
} Element;
void factor(char* s, int & sn, Element* eles, int& en);
void term(char* s, int & sn, Element* eles, int& en);
void expr(char* s, int & sn, Element* eles, int& en);
int resolve(Element* eles, int& end)
{
int end_t = end--;
if(eles[end_t].is_op)
{
int operand2 = resolve(eles, end);
int operand1 = resolve(eles, end);
switch(eles[end_t].val)
{
case '+': return operand1 + operand2;
case '-': return operand1 - operand2;
case '*': return operand1 * operand2;
case '/': return operand1 / operand2;
}
}
else
{
return eles[end_t].val;
}
}
void factor(char* s, int & sn, Element* eles, int& en)
{
int op = s[sn++];
if(op == '(')
{
expr(s, sn, eles, en);
sn++;
}
else
{
eles[en].is_op = false;
eles[en++].val = op - '0';
}
}
void term(char* s, int & sn, Element* eles, int& en)
{
factor(s, sn, eles, en);
while(s[sn] == '*' || s[sn] == '/')
{
int op = s[sn++];
factor(s, sn, eles, en);
eles[en].is_op = true;
eles[en++].val = op;
}
}
void expr(char* s, int & sn, Element* eles, int& en)
{
term(s, sn, eles, en);
while(s[sn] == '+' || s[sn] == '-')
{
int op = s[sn++];
term(s, sn, eles, en);
eles[en].is_op = true;
eles[en++].val = op;
}
}
void print_elements(Element* eles, int sn)
{
for(int i = 0; i < sn; i++)
{
if(eles[i].is_op)putchar(eles[i].val);
else putchar(eles[i].val + '0');
}
putchar('\n');
}
int main()
{
char s[256];
Element eles[256];
int sn, en;
while(scanf("%s", s) != EOF)
{
sn = en = 0;
expr(s, sn, eles, en);
print_elements(eles, en);
printf("%d\n", resolve(eles, --en));
}
return 0;
}