C++ 支持加减乘三种运算和括号的计算器

刷题——支持加减乘三种运算和括号的计算器

以"12+(2*(3-4))*5"为例子,利用递归的方法。

    //以"12+(2*(3-4))*5"为例子
    int solve(string s)
    {
        //返回对应数值
        if (s.empty()) return 0;
        else
        {
            int result = 0;
            for (size_t i = 0; i < s.size(); i++)//如果是数字,例如“12”,返回对应数值12
                if (s[i] >= '0'&&s[i] <= '9')
                {
                    result = 10 * result + (s[i] - '0');
                    if (i == s.size() - 1) return result;
                }
                else//如果是式子,例如“2*(3-4)”,则继续运行,将式子分块
                    break;
        }
        //将式子分块
        vector<string> elems;//保存元素块,如“12”,“2*(3-4)”,“5”等
        vector<char> op; //保存该层式子的运算符(不包括在括号中的)
        op.push_back('+');//为了将结果加入result第一个运算符必须是+
        vector<char> left;//记录左括号数量
        vector<char> right;//记录右括号数量
        int i = 0;//当前元素块
        for (auto it = s.begin(); it != s.end(); )
        {
            if (*it >= '0'&&*it <= '9')//将数值型元素块加入elems
            {
                elems.push_back("");
                for (; it != s.end() && *it >= '0'&&*it <= '9'; ++it)
                    elems[i].push_back(*it);
                ++i;
            }
            else if (*it == '+' || *it == '-' || *it == '*')//将运算符加入op
            {
                op.push_back(*it);
                ++it;
            }
            else if (*it == '(')//将式子(带括号)元素块去掉最外侧括号后加入elems
            {
                elems.push_back("");
                std::string& temp = elems[i];
                while (it != s.end() && (left.size() != right.size() || *it == '('))
                {
                    if (*it == '(') left.push_back(*it);
                    else if (*it == ')') right.push_back(*it);
                    temp.push_back(*it);
                    ++it;
                }
                temp = temp.substr(1, temp.size() - 2);//去掉最外侧括号
                ++i;
            }
            else ++it;
        
        }
        //计算当前分式子的值
        int result = 0;
        for (int i = 0;i < op.size();++i)
        {
            char o = op[i];//当前运算符
            if (i + 1 < op.size())//由于乘法运算*是优先的,所以需要先预测后一位运算符是不是*
            {
                int temp = solve(elems[i]);
                while(i+1<op.size()&&op[i + 1] == '*')//如果后面的*,则先乘起来
                {
                    temp *= solve(elems[i + 1]);
                    ++i;
                }
                switch (o)//再更加当前符号进行加减处理
                {
                case '+':result += temp;break;
                case '-':result -= temp;break;
                }
            }
            else//由于乘法必然已经运算,所以剩下的只有加减法运算。
            {
                switch (o)
                {
                case '+':result += solve(elems[i]);break;
                case '-':result -= solve(elems[i]);break;
                }
            }
        }
        return result;//返回结果
    }

该方法代码量较大,约90行。有的方法的代码量只有30行左右,但本人能力有限,独自想不出来。

 

posted @ 2021-06-25 11:07  mshentai  阅读(239)  评论(0编辑  收藏  举报