基本计算器

力扣网

题目描述:实现一个基本的计算器来计算一个简单的字符串表达式的值。

字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -非负整数和空格  

class Solution {
public:
    stack<char> fuhao;
    stack<int> num;
    vector<char> pre_fuhao;
    vector<int> pre_num;
    
    int type_change(string s){  //类型转换
            stringstream ss;
            ss<<s;
            int a;
            ss>>a;
            return a;
        }
    int calculate(string s) {   //计算器功能实现
        pre_cal(s);
        if(pre_num.size()==1){
            return pre_num[0];
        }
        stack<char> str_f;
        stack<int> str_n;
        auto b = pre_num.begin();
        str_n.push(*b);
        for(int i = 0;i<pre_fuhao.size();i++){
            if(pre_fuhao[i]==')'){
                num.push(str_n.top());
                str_n.pop();
                while(str_f.top()!='('){
                    if ((str_f.top() == '+')||(str_f.top() == '-')){

                        fuhao.push(str_f.top());
                        str_f.pop();
                        num.push(str_n.top());
                        str_n.pop();
                    }
                }
                str_f.pop();
                int ans = sub_cal(fuhao,num);
                str_n.push(ans);
                num.pop();
            }
            else str_f.push(pre_fuhao[i]);
            if((pre_fuhao[i]=='+')||(pre_fuhao[i]=='-')){
                b++;
                str_n.push(*b);
            }
        }
        while(!str_f.empty()&&!str_n.empty()){
            num.push(str_n.top());
            str_n.pop();
        }
        while(!str_f.empty()){
            fuhao.push(str_f.top());
            str_f.pop();
        }
        if(!fuhao.empty()){
            int ans = sub_cal(fuhao,num);
            return ans;
        }
        return str_n.top();
    }
    
    void pre_cal(string str){    //输出字符串预处理
        vector<char> ans;
        for(int i = 0;i<str.size();i++){
            if(str[i]!=' '){
                if ('0'<=str[i]&&str[i]<='9'){
                    ans.push_back(str[i]);
                }
                if((!('0'<=str[i]&&str[i]<='9')||i==str.size()-1)&&!(ans.empty())){
                    string s = "";
                    for(int j = 0;j<ans.size();j++){
                        s+=ans[j];
                    }
                    ans.clear();
                    int a = type_change(s);
                    pre_num.push_back(a);
                }
                if(!('0'<=str[i]&&str[i]<='9')){
                    pre_fuhao.push_back(str[i]);
                };
            }
        }
        if(!ans.empty()){
            string s = "";
            for(int j = 0;j<ans.size();j++){
                s+=ans[j];
            }
            ans.clear();
            int a = type_change(s);
            pre_num.push_back(a);
        }
    }
    
    int sub_cal(stack<char>& fuhao,stack<int>& num){    //子串计算
    while(!fuhao.empty()){
        if(fuhao.top()=='+'){
            fuhao.pop();
            int n1 = num.top();
            num.pop();
            int n2 = num.top();
            num.pop();
            num.push(n1+n2);
        }
        else if(fuhao.top()=='-'){
            fuhao.pop();
            int n1 = num.top();
            num.pop();
            int n2 = num.top();
            num.pop();
            num.push(n1-n2);
        }
    }
    return num.top();
}
};

按照自己最原始的思路写的,比较麻烦。总共有四个函数,int type_change(string s)是为了方便类型转换所写的,void pre_cal(string str)负责将数字与字符分开,主要为了处理两位以上的字符转数字这一问题,直接用一个整型容器进行存储了,int calculate(string s)是实现计算器功能的主要函数,遍历预处理后的字符容器与整型容器,不断压入整型栈与字符栈,直到遇到闭括号,再依次弹出至开括号,并将结果压入存储子串处理的栈中,int sub_cal(stack<char>& fuhao,stack<int>& num)进行子串处理,将只包含运算符号与数字的栈依次弹出并计算,最终返回计算结果,然后将结果压入calculate函数的整型栈中,继续以上流程,直到遍历结束。

当字符串中不包含括号时,不会进行弹出操作,此时以遍历结束作为触发条件,判断字符栈中若有元素,则进行弹出、压入、计算操作。

参考了题解区代码,绘制如上图所示的计算器函数流程图。首先,因为涉及到多位数情况,下标变化不一定都是1,所以采用while循环进行处理,使用stoi与string代替预处理函数进行整型变换功能,同时在num最前面插入0,根据加减情况对数字的正负进行赋值,将减法运算简化为加法运算,以此代替子串处理函数。并将乘除法优先计算,保证对开闭括号处理时只执行加减法。

class Solution {
public:
    int calculate(string s) {
        stack<char> opr;
        stack<int> num;
        num.push(0);
        int index = 0;
        while(index<s.size()){  //用while不用for,当两位数时需要多加一次
            if(s[index]==' '){
                index++;
            }
            else if((s[index]=='(')||(s[index]=='+')||(s[index]=='-')||(s[index]=='*')||(s[index]=='/')){
                opr.push(s[index]);
                index++;
            }
            else if(s[index]==')'){
                int a = 0;
                while(opr.top()!='('){
                    a+=(opr.top()=='-'?-num.top():num.top());
                    num.pop();
                    opr.pop();
                }
                a+=num.top();
                num.pop();
                opr.pop();
                num.push(a);
                index++;
            }
            else{
                string str ="";
                while(index<s.size()&&('0'<=s[index])&&(s[index]<='9')){
                    str+=s[index];
                    index++;
                }
                num.push(stoi(str));
                if(!opr.empty()&&(opr.top()=='*'||opr.top()=='/')){
                    int a = num.top();
                    num.pop();
                    int b = num.top();
                    num.pop();
                    num.push(opr.top()=='*'?(a*b):(b/a));
                    opr.pop();
                }
            }
        }
        int ans = 0;
        while(!opr.empty()){
            ans+=(opr.top()=='+'?num.top():-num.top());
            num.pop();
            opr.pop();
        }
        return ans+num.top();
    }
};

接下来可以考虑学习逆波兰表达式

class Solution {
public:
    stack<int> num;
    stack<char> op;
    int pri(char a){
        switch(a){
        case '+': return 1;
        case '-': return 1;
        case '*': return 2;
        case '/': return 2;
        case '(': return 3;
        default: return -1;
        }
    }
    void cal(){
        int b=num.top();num.pop();
        int a=num.top();num.pop();
        switch(op.top()){
        case '+':num.push(a+b);break;
        case '-':num.push(a-b);break;
        case '*':num.push(a*b);break;
        case '/':num.push(a/b);break;
        }
        op.pop();
    }
    int calculate(string s) {
        string ss;
        for(int i=0;i<(int)s.size();i++){
            if(isdigit(s[i]))
                ss+=s[i];
            else if(s[i]==' ') continue;
            else{
                if(!ss.empty()){
                    num.push(stoi(ss));
                    ss.clear();
                }
                if(op.empty()||s[i]=='('||pri(op.top())<pri(s[i]) )
                    op.push(s[i]);
                else if(s[i]==')'){
                    while(op.top()!='(') cal();
                    op.pop();
                }
                else{
                    if(!op.empty()&&pri(op.top())>=pri(s[i])&&pri(op.top())!=3) cal();
                    op.push(s[i]);
                }
            }
        }
        if(!ss.empty()) num.push(stoi(ss));
        while(!op.empty()) cal();
        return num.top();
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值