**题目:**Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero.
题目理解: 题目意思很好理解啦!就是写一个字符串表达式值得计算,主要考察的对数据结构—栈 的使用,考察不同运算符的优先级。当然自己在做这题的时候,有去考虑括号的处理,自己第一遍A的代码就特别长。代码截图如下
int op_cal(int t1,int t2,char ch)
{
if(ch=='+')
return t1+t2;
else if(ch=='-')
return t1-t2;
else if(ch=='*')
return t1*t2;
else if(ch=='/')
return t1/t2;
}
int compareop(char ch1,char ch2)//compare the priotity
{
if(ch1=='(')
return 0;
if(ch1=='+')
{
return 0;
}
if(ch1=='-')
{
if(ch2=='+'||ch2=='-')
return 1;
else
return 0;
}
if(ch1=='*'||ch1=='/')
return 1;
}
int calculate(string s1)
{
vector<char> s;
for(int j=0;j<s1.size();j++)
{
if(s1[j]!=' ')
s.push_back(s1[j]);
}
if(s.size()==0)
return 0;
int i=0;
stack<int> inter;
stack<char> op;
bool brac=false;
while(i<s.size())
{
if(isdigit(s[i]))
{
int te=0;
while(isdigit(s[i])&&i<s.size())
{
te =te *10+s[i]-'0';
i++;
}
inter.push(te);
}
else
{
if(op.size()==0)
op.push(s[i]);
else if(s[i]=='(')
op.push(s[i]);
else if(s[i]==')')
{
while(op.top()!='(')
{
int t1=inter.top();
inter.pop();
int t2=inter.top();
inter.pop();
char te=op.top();
inter.push(op_cal(t2,t1,te));
op.pop();
}
op.pop(); //the operation in bracket are completed
}
else
{
while(op.size()!=0)
{
int temp=compareop(op.top(),s[i]);
if(temp==1)
{
int t1=inter.top();
inter.pop();
int t2=inter.top();
inter.pop();
cout<<op_cal(t2,t1,op.top())<<endl;
inter.push(op_cal(t2,t1,op.top()));
op.pop();
}
else
{
break;
}
}
op.push(s[i]);
}
i++;
}
}
while(op.size()!=0)
{
int t1=inter.top();
inter.pop();
int t2=inter.top();
inter.pop();
inter.push(op_cal(t2,t1,op.top()));
op.pop();
}
return inter.top();
}
上面就是自己写的代码,思路很简单,每次先匹配字符,如果是数字,那么就把它丢到一个专门存储数值的栈中,这里需要考虑的就是如果是多位数的时候,要多计算几次。然后接着匹配,如果匹配到的是运算符,就要多考虑一下。对于左括号(题目中不会有括号),那么直接入栈。对于其它运算符,加号,减号,乘号,除法就需要多考虑一些。这里有一个专门存储运算符的栈,每次把匹配到的字符串为运算符的字符串和栈中的运算符进行比较,然后依据情况看是否需要进行运算。这样下去就可以把最后的结果给 算出来。其中比较的过程如下:
设ch1为运算符栈顶,ch2为字符串中匹配的运算符
1、ch1是加法,那么无论ch2是什么运算符,都可以选择放到后面去算。
2、ch1是减法,如果ch2是加法或者减法,那么前面是肯定需要先计算数值呢!
3、ch1是乘法或者除法的时候都选择先算值。
其中计算完一次值后就要把该运算符所在的栈pop一下。然后再把下一个运算符拿出来继续当成ch1再和ch2进行比较,其中比较的过程和上面的相同。
基本上按这样的一个流程,就可以把一个算式最后的值给计算出来。但是自己后面又去看了一下答案发现有更简单的方法。
更简洁的方法:我们思考一个问题,对于运算符为‘-’或者‘+’的时候,我们真的需要考虑那么多吗?对于一个减号的运算符,我们是不是可以把它和后面的一个数组合起来,把它变成它的相反数,丢到堆栈里面。对于加号的运算符就只要把它本身给丢到栈中;如果遇到的是一个乘号或者除号就直接进行计算。最后这些数值都被丢到一个只有整数的栈,然后可以看成是所有数相加把最后的结果算出来。这样做的话比前面的方法简洁很多,忽略掉了比较运算符的优先级。代码也简洁了很多。
int calculate(string s)
{
if(s.size()==0)
return 0;
char op='+';
int temp=0;
stack<int> inter;
for(int i=0;i<s.size();i++)
{
if(isdigit(s[i]))
temp=temp*10+s[i]-'0';
if(!isdigit(s[i])&&!isspace(s[i])||i==s.size()-1)
{
if(op=='-')
inter.push(-temp);
else if(op=='+')
inter.push(temp);
else
{
int t=0;
if(op=='*')
t=inter.top()*temp;
else
t=inter.top()/temp;
inter.pop();
inter.push(t);
}
temp=0;
op=s[i];
}
}
int ans=0;
while(!inter.empty())
{
ans +=inter.top();
inter.pop();
}
return ans;
}
总结:这题自己想的时候做了好久,不断的处理特殊情况。但是没有想用一种更加简洁的方法去做!还是要多思考啊,多学习。