输入字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。
算术表达式的有效性由调用者保证;
输入描述:
输入一个算术表达式
输出描述:
得到计算结果
输入示例:
3+2*{1+2*[-4/(8-6)+7]}
输出示例:
25
使用两个栈,一个栈用来保存当前操作符,一个栈用来保存操作数。
从前往后遍历字符串:
当遇到数字时直接压入操作数栈;
当遇到正括号 (、[、{ 时直接压入操作符栈;
当遇到乘号或者除号时,判断前一个操作符(即操作符栈栈顶元素)是否为除号,如果前一个操作符为除号则先从操作数栈弹出栈顶两个元素计算除号,除法结果压入操作数栈,然后从操作符栈弹出除法操作符;
当遇到加号或者减号时,如果这个加号或减号是输入字符串的第一个字符时,或者字符串前一个字符为正括号 (、[、{ 时,在操作数栈栈顶压入一个 0, 如果不是这种情况再继续考虑,如果前一个操作符(即操作符栈顶元素)是否为乘号或者除号或者减号,如果是乘号或者除号,就一直从操作数栈弹出两个元素进行乘法或者除法运算,结果压入操作数栈,一直进行到前一个操作符不再是乘号或者除号为止,如果前一个操作符为减号,则也先从操作数栈弹出两个元素进行减法运算,结果压入操作数栈;
当遇到反括号 )、]、} 时, 从操作数栈弹出两个元素,从操作符栈弹出一个操作符,进行算术运算,指导操作符栈栈顶元素为对应的正括号 (、[、{ 时停止进行算术运算,并将正括号从操作符栈弹出。
当输入字符串遍历结束以后,如果操作符栈不为空,则操作数栈弹出两个元素,从操作符弹出一个操作符,进行算术运算,直到操作符栈为空,这个过程相当于最后的表达式从后往前计算,因为有前面的判断逻辑保证,逆序计算不会影响结果。
上述整个过程结束后,操作符栈为空,操作数栈中只剩下整个表达式计算的结果值,返回该结果,弹出栈即可。
代码:
#include
#include
#include
using namespace std;
double calculate(string s)
{
stack num;
stack op;
string temp = "";
for(int i = 0; i < s.length(); i++)
{
if(s[i] >= '0' && s[i] <= '9')
{
temp += s[i];
}
if((s[i] < '0' || s[i] > '9') && temp != "")
{
num.push(atoi(temp.c_str()));
temp = "";
}
if(s[i] == '(' || s[i] == '[' || s[i] == '{')
{
op.push(s[i]);
}
if(s[i] == '*' || s[i] == '/')
{
if(!op.empty())
{
char lastop = op.top();
if(lastop == '/')
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
num.push(firstnum*1.0/secondnum);
op.pop();
}
}
op.push(s[i]);
}
if(s[i] == '+' || s[i] == '-')
{
if(i == 0 || s[i-1] == '(' || s[i-1] == '[' || s[i-1] == '{')
{
num.push(0);
}
if(!op.empty())
{
char lastop = op.top();
while(!op.empty() && (lastop == '*' || lastop == '/'))
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
if(lastop == '*')
num.push(firstnum*secondnum);
else if(lastop == '/')
num.push(firstnum*1.0/secondnum);
op.pop();
if(!op.empty())
lastop = op.top();
}
if(lastop == '-')
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
num.push(firstnum-secondnum);
op.pop();
}
}
op.push(s[i]);
}
if(s[i] == ')')
{
if(!op.empty())
{
char lastop = op.top();
while(!op.empty() && lastop != '(')
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
switch(lastop)
{
case '+':
num.push(firstnum+secondnum);
break;
case '-':
num.push(firstnum-secondnum);
break;
case '*':
num.push(firstnum*secondnum);
break;
case '/':
num.push(firstnum*1.0/secondnum);
break;
}
op.pop();
if(!op.empty())
lastop = op.top();
}
if(lastop == '(')
op.pop();
}
}
if(s[i] == ']')
{
if(!op.empty())
{
char lastop = op.top();
while(!op.empty() && lastop != '[')
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
switch(lastop)
{
case '+':
num.push(firstnum+secondnum);
break;
case '-':
num.push(firstnum-secondnum);
break;
case '*':
num.push(firstnum*secondnum);
break;
case '/':
num.push(firstnum*1.0/secondnum);
break;
}
op.pop();
if(!op.empty())
lastop = op.top();
}
if(lastop == '[')
op.pop();
}
}
if(s[i] == '}')
{
if(!op.empty())
{
char lastop = op.top();
while(!op.empty() && lastop != '{')
{
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
switch(lastop)
{
case '+':
num.push(firstnum+secondnum);
break;
case '-':
num.push(firstnum-secondnum);
break;
case '*':
num.push(firstnum*secondnum);
break;
case '/':
num.push(firstnum*1.0/secondnum);
break;
}
op.pop();
if(!op.empty())
lastop = op.top();
}
if(lastop == '{')
op.pop();
}
}
}
if(temp != "")
num.push(atoi(temp.c_str()));
while(!op.empty())
{
char lastop = op.top();
double secondnum = num.top();
num.pop();
double firstnum = num.top();
num.pop();
switch(lastop)
{
case '+':
num.push(firstnum+secondnum);
break;
case '-':
num.push(firstnum-secondnum);
break;
case '*':
num.push(firstnum*secondnum);
break;
case '/':
num.push(firstnum*1.0/secondnum);
break;
}
op.pop();
}
if(num.empty())
return 0;
double value = num.top();
num.pop();
return value;
}
void test1()
{
string s;
while(cin >> s)
{
cout << calculate(s) << endl;
}
}
int main()
{
test1();
return 0;
}