表达式求值是程序设计编译中的一个最基本的问题,他的实现是栈应用的一个典型范例:
表达式中包含的运算符有(,),+,-,*,/
,共七种运算符,我们首先要确定这七种运算符的优先级,显然()
的优先级最高,*,/
次之,+,-
的优先级最低,那么(
与)
、+
与+
、-
与-
⋯ \cdots ⋯,这些优先级又怎么区分呢?我么用栈求表达式值时是将运算符存在栈中,例如当前栈中有+
,当再来+,-
时,显然栈中的+
可以出栈了,那么栈中+
的优先级就高于栈外的+,-
,因此优先级相同的运算符在栈内的优先级应该高于栈外的优先级。下面以表格的形式给出各运算符的优先级:
操作符 | # | ( | *, / | +, - | ) |
---|---|---|---|---|---|
isp | 0 | 1 | 5 | 3 | 6 |
icp | 0 | 6 | 4 | 2 | 1 |
int Isp(char ch){
int k;
switch(ch){
case '#': k = 0; break;
case '(': k = 1; break;
case '*': k = 5; break;
case '/': k = 5; break;
case '+': k = 3; break;
case '-': k = 3; break;
case ')': k = 6; break;
}
return k;
}
int Icp(char ch){
int k;
switch(ch){
case '#': k = 0; break;
case '(': k = 6; break;
case '*': k = 4; break;
case '/': k = 4; break;
case '+': k = 2; break;
case '-': k = 2; break;
case ')': k = 1; break;
default: k = -1;
}
return k;
}
这里介绍两种表达式求值的思路:
1. 直接求值法
直接法顾名思义就是直接计算,不需要事先处理表达式;该方法需要两个栈,栈nsta
存数字,栈osta
存运算符,一次遍历表达式字符串,这会出现一下几种操作:
- 当前字符是数字时,直接压入
nsta
; - 当前字符是运算符时:
isp(osta.top) < icp(ch)
,ch
直接入栈;isp(osta.top) > icp(ch)
,osta.top
出栈,运算结果压入nsta
,重复步骤1;isp(osta.top) == icp(ch)
,只有两种可能,isp('(') == icp(')')
,isp('#') == icp('#')
,第一种情况左括号出栈,第二种情况表达式计算结束。
对应直接的直接发代码如下:
void directCalc(char str[]){
stack<int> nsta; //运算数栈
stack<char> osta; //运算符栈
int len = strlen(str);
str[len++] = '#';
osta.push('#');
int a, b;
for(int i=0; i<len; i++){
char tmp1 = str[i];
char tmp2 = osta.top();
if(tmp1 >= '0' && tmp2 <= '9')
nsta.push(tmp1-'0');
else{
if(Isp(tmp2) < Icp(tmp1))
osta.push