參考其他網友的思路,改了原來的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;
}