力扣网
题目描述:实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 (
,右括号 )
,加号 +
,减号 -
,非负整数和空格
。
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();
}
};