参考其他网友的思路,改了原来的bug。对浮点数、整数都适用。
维护三个栈,分别存括号、 + -*/ 、数字
首先遍历匹配括号,取出括号内的子字符串;
然后计算只包括 + -*/ 及数字的子字符串的结果,先计算* / ,将 + -全部入栈,然后计算只包含 + -的结果。
#include<iostream>
#include<string>
#include<sstream>
#include<stack>
#include<algorithm>
using namespace std;
double calc(string s)
{
char c;//符号
double a, b, val;//左操作数、右操作数、计算结果
stack<double> num;//存数字
stack<char> op;//存操作符
//以+或-开头,在开头补零
if (s[0] == '+' || s[0] == '-')
{
s = "0" + s;
}
//将第一个数字压入数字栈
stringstream ss(s);
ss >> val;
num.push(val);
//每次读取一个符号和数字
while (ss >> c >> val)
{
//如果符号是*/,直接与前面的数计算,消去*/
if (c == '*' || c == '/')
{
if (c == '*')
{
val *= num.top();
}
else
{
val = num.top() / val;
}
num.pop();//弹出已经计算过的数
num.push(val);//压入计算后的结果
}
else//符号是+-
{
//将取到的数和符号压栈,op栈中只留+-
num.push(val);
op.push(c);
}
}
//操作符栈不为空,只有加减运算
while(!op.empty())
{
a = num.top();
num.pop();
b = num.top();
num.pop();
if (op.top() == '+')
{
num.push(b + a);
}
else
{
num.push(b - a);
}
op.pop();
}
return num.top();
}
int main()
{
string str;//表达式字符串
getline(cin, str);
stack<int> kuohao;//存括号
int len = str.size();
int from, to;
for (int i = 0; i < len; i++)
{
if (str[i] == '(' || str[i] == ')')
{
//括号不匹配
if (kuohao.empty() || str[i] == str[kuohao.top()])
{
kuohao.push(i);//栈里存放的是'('')'在str中的index
}
else//括号匹配
{
from = kuohao.top();
to = i; //定位到一组()
kuohao.pop();//计算过的出栈
//求解括号中的表达式
double tmp = calc(str.substr(from + 1, to - from - 1));
//把所求结果替换掉括号部分的表达式
stringstream ss;
ss << tmp;
string tmpS;
ss >> tmpS; //double->string
str.replace(str.begin() + from, str.begin() + to + 1, tmpS.begin(), tmpS.end());//'('...')'之间有to-from+1个字符!
len = str.size();//循环条件记得更新
i = from - 1;
}
}
}
double result = calc(str);
cout << result << endl;
return 0;
}