中缀表达式计算

思路:每次都优先寻找最小优先级的运算符位置,然后分割表达式:

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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值