c++使用栈实现表达式四则运算

前言

之前学数据结构的时候用栈写四则运算不太会,觉得网上的代码和课本里的逻辑很怪,比较难理解。但这个又很经典,据说面试还可能会考到。这里某天有灵感的时候就记录下来了。


源代码

先上源代码,再来解释具体的细节。

# include <iostream>
# include <stack>
# include <cmath>
using namespace std;

int getPriority(char op);
float cal_one(float n1, char op, float n2);

float cal(const string& s)
{
    
    
    string str = s;
    float n1, n2, tn;
    int lastPriority = 0, priority;
    char op;
    stack <float> numS;
    stack <char> opS;
    float result = 0;
    for(int i = 0; i < s.length(); i++){
    
    
        // 数字
        if (str[i] >= '0' && str[i] <= '9'){
    
    
            tn = tn * 10 + float(str[i] - '0');
        } else if (str[i] == ' '){
    
    
            continue;
        } else {
    
    
            numS.push(tn);
            priority = getPriority(str[i]);
            if (priority <= lastPriority){
    
     // 优先级一样活着低于上一个操作符
                while (!opS.empty()){
    
    
                    op = opS.top();
                    lastPriority = getPriority(op);

                    if (lastPriority >= priority) {
    
    
                        opS.pop();
                        n2 = numS.top();
                        numS.pop();
                        n1 = numS.top();
                        numS.pop();
                        n1 = cal_one(n1, op, n2);
                        numS.push(n1);
                    }
                }
                opS.push(str[i]);
            } else {
    
     // 优先级高于上一个
                opS.push(str[i]);
            }
            tn = 0;
            lastPriority = priority;
        }
    }
    //把最后一个操作数也加上
    numS.push(tn);

    while (!opS.empty()){
    
    
        op = opS.top();
        opS.pop();
        n2 = numS.top();
        numS.pop();
        n1 = numS.top();
        numS.pop();
        result = cal_one(n1, op, n2);
        numS.push(result);
    }
    return result;
}

int getPriority(char op)
{
    
    
    // -1 代表没有找到对应运算符
    int priority = -1;
    if (op == '+' || op == '-')
        priority = 1;
    else if (op == '*' || op == '/')
        priority = 2;
    else if (op == '^')
        priority = 3;
    return priority;
}

float cal_one(float n1, char op, float n2){
    
    
    float result = 0;
    switch (op) {
    
    
        case '+':
            result = n1 + n2;
            break;
        case '-':
            result = n1 - n2;
            break;
        case '*':
            result = n1 * n2;
            break;
        case '/':
            result = n1 / n2;
            break;
        case '^':
            result = pow(n1, n2);
            break;
    }
    return result;
}


int main(){
    
    
    cout << "2 ^ 3 + 5 * 8 - 3 / 2 = " << cal("2 ^ 3 + 5 * 8 - 3 / 2") << endl;
    return 0;
}

这里相信大家都已经看出来,getPriority就是获取操作符优先级的,cal_one就是获取某个式子的正则运算的。关键部分在cal函数里面。

  • cal函数的主要思想是,先遍历字符串的一个个字符,识别出数字(中途有空格都无所谓,因为加了个else if(str[i) == ’ ')就直接continue了), 然后遇到操作符就应该考虑和上一个字符的优先级,如果优先小于等于上一个,那么此时上一个操作符就可以从栈里拿出来运算了。然后在判断上上个操作符,以此类推,这里使用STL中的stack会比较方便。最后记得把最后一个操作数加进去,然后把最后的运算给迭代运算完。
  • 为什么最后可以直接出栈运算呢?
    因为按照我们的思路,在栈里面的优先级都是从栈底到栈顶递增的,此时按出栈运算刚好是从栈内的优先级高的先运算,保证了算法的正确性。

运行结果:
在这里插入图片描述





扩展1: 支持输入是浮点数

这个由于时间关系,我就不去全部写出来了,不过这里有个例子可以供大家参考。

# include <iostream>
# include <cmath>
using namespace std;

float string2float(string s)
{
    
    
    float n = 0;
    bool isXiaoShu = false; // 判断当前的数字是不是小数部分
    int xiaoShuLength = 0;  // 记录小数部分的长度
    for (int i = 0; i < s.length(); i++){
    
    
        if (s[i] >= '0' && s[i] <= '9'){
    
    
            n = n * 10 + float (s[i] - '0');
            if (isXiaoShu)
                xiaoShuLength++;
        }
        else if (s[i] == '.'){
    
    
            isXiaoShu = true; //开始进入小数部分
        }
    }
    return n * 1.0 / pow(10, xiaoShuLength);
}

int main()
{
    
    
    float num = string2float("4.28");
    cout << num;
}

运行结果:
运行结果




扩展2: 支持括号运算

这里我给个思路,就是我们可以把运算符的权重定义为 priority + bracketPrioriy,

  • 其中,priority和我们之前说的完整代码里的priority一样
  • bracketPrioriy呢, 每次我们检测到 左括号 ( 的时候,我们就让bracketPrioriy += 10(bracketPrioriy初始为0, 且这里的10不是固定的,只要足够让括号里的运算符大于括号外的运算符即可),然后遇到 ) 的时候,我们就让bracketPrioriy -= 10,并且迭代出栈运算,一直等到出栈的运算符是 ( , 其他与完整代码的例子的思路一样。

猜你喜欢

转载自blog.csdn.net/weixin_43850253/article/details/108512372