思路:每次都优先寻找最小优先级的运算符位置,然后分割表达式:
1.优先寻找最小优先级的运算符位置。
2.以当前最小优先级运算符位置分割字符串。
3.判断当前字符串是否可再分,如果是不可分割字符串,则计算出当前运算符的位置中的数字,返回这个数字。否则,继续返回第一步继续计算左串和右串。
4.将不可再分的结果进行基本四则运算。
例如表达式1+(40/2+7-3*2):
1.执行第一步找到第一个'+'号的位置。
2.分割字符串表达式为1+,(40/2+7-3*2)。
3.判断当前字符串可再分。
4.计算左表达式得到1,左表达式不可再分返回1。
5.计算右表达式找到最小优先级位置为'-'号位置。分割表达式为(40/2+7-,3*2)。
6.判断当前字符串可再分,先计算左表达式。
7.分割左表达式找到最小优先级'+'号位置。分割为(40/2+,7。
8.判断当前字符串可再分,先计算左表达式。
9.分割左表达式找到最小优先级'/'号位置。分割为(40/,2。
10.判断左字符串不可再分,计算出左表达式值为40,判断右字符串不可再分,计算出右表达式值为2。
11.对当前字符串进行四则运算得到结果20,返回上一步。
12.计算第7步得到的右字符串重复,得到40/2+7的结果为27,返回上一步。
13.计算第5步得到的右字符串重复,依次得到3*2,40/2+7-3*2的结果为21,返回上一步。
14.计算第2步得到的两个字符串,得到1+(40/2+7-3*2)的结果为22,返回最终结果。
总结:整个过程通过分割字符串得到一个表达式树,通过深度优先搜索计算出子树的结果最终得到根节点的结果。
代码如下:
#define MAXPRI 0x0FFFFFFE
int
calc(char* str, int l, int r) {
int op = -1, pri = MAXPRI - 1, cur_pri, temp_pri = 0;
// 寻找最小优先级位置
for (int i = l; i < r; ++i) {
cur_pri = MAXPRI;
switch (str[i]) {
case '(':
temp_pri += 100;
break;
case ')':
temp_pri -= 100;
break;
case '+':
case '-':
cur_pri = temp_pri + 1;
break;
case '*':
case '/':
cur_pri = temp_pri + 2;
break;
}
if (cur_pri <= pri) {
op = i;
pri = cur_pri;
}
}
// 剩下的是数字
if (op == -1) {
int num = 0;
for (int i = l; i < r; ++i) {
if (str[i] < '0' || str[i] > '9')
continue;
num = num * 10 + str[i] - '0';
}
return num;
}
int a = calc(str, l, op);
int b = calc(str, op + 1, r);
switch (str[op]) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
}
return 0;
}