讀入一個只包含 +, -, *, / 的非負整數計算表達式,計算該表達式的值。
輸入:
測試輸入包含若干測試用例,每個測試用例佔一行,每行不超過200個字符,整數和運算符之間用一個空格分隔。沒有非法表達式。當一行中只有0時輸入結束,相應的結果不要輸出。
輸出:
對每個測試用例輸出1行,即該表達式的值,精確到小數點後2位。
樣例輸入:
1 + 2
4 + 2 * 5 - 7 / 11
0
樣例輸出:
3.00
13.36
關於四則運算,這裏可以引申一下幾個概念,中綴表達式,後綴表達式。一般我們的四則運算,給出的表達式是中綴表達式,而我們求解四則運算的方法就是先把中綴表達式轉換成後綴表達式,再求得結果。無論是中綴表達式轉換成後綴表達式,還是後綴表達式求結果,都用到了棧。
中綴轉後綴(棧存儲操作符):如果遇到操作數,直接輸出。如果遇到操作符,那麼從棧中彈出元素直到發現優先級更低的元素爲止。(例外:除非是在處理")",否則絕不移走"(",所以"("的優先級最高。)再將操作符壓入棧中。如督導文件末尾,再將棧元素彈出變成空棧寫到輸出中。舉例: 1 + 2 * 3 ,則轉換成的後綴表達式爲1 2 3 * + 。
後綴求結果(棧存數字):當遇到一個數字的時候就存入棧中,當遇到一個操作符時,把該操作符作用於從棧彈出來的兩個數上,再將所得結果壓入棧中。最後把棧頂元素輸出(此時棧也只有一個元素了)即爲這個四則運算的結果。
這是我很久以前寫過的代碼,還可以包含括號,AC了。
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <sstream>
#include <cstdlib>
using namespace std;
int Judge(const string& sval) //判斷一個字符串是否爲數字 這個比atoi好用 atoi不能識別字符串0
{
int val;
stringstream ss;
ss << sval;
ss >> val;
if(ss.fail())
return -1;
return val;
}
double evalPostFix(const vector<string> &str) //後綴表達式計算結果 棧存的是數字
{
stack<double> s;
for(int i = 0; i != str.size(); ++i)
{
if(Judge(str[i]) != -1) //如果字符串爲數字 則放入棧中
s.push(atoi(str[i].c_str()));
else if(str[i] == "+")
{
double a = s.top();
s.pop();
double b = s.top();
s.pop();
s.push(b + a);
}
else if(str[i] == "-")
{
double a = s.top();
s.pop();
double b = s.top();
s.pop();
s.push(b - a);
}
else if(str[i] == "*")
{
double a = s.top();
s.pop();
double b = s.top();
s.pop();
s.push(b * a);
}
else if(str[i] == "/")
{
double a = s.top();
s.pop();
double b = s.top();
s.pop();
if(a == 0)
{
cout << "0不能作除數" << endl;
continue;
}
s.push(b / a);
}
else
continue;
}
return s.top();
}
vector<string> inToPostfix(const vector<string> &str) //中綴表達式轉後綴表達式 棧存的是符號
{
stack<string> s;
vector<string> e;
for(int i = 0; i != str.size(); ++i)
{
if(Judge(str[i]) != -1) //如果該字符串爲數字 則放入輸出中
e.push_back(str[i]);
else //挨個分析運算符,共六種
{
if(str[i] == "(") //因爲(優先級最高 所以下面的while判斷都要進行
s.push("(");
else if(str[i] == ")")
{
while(!s.empty() && s.top() != "(")
{
e.push_back(s.top());
s.pop();
}
s.pop(); //把"("出棧
}
else if(str[i] == "+" || str[i] == "-")
{
while(!s.empty() && s.top() != "(") //如果輸入的是 "+" 或"-",則把棧中所有元素拿出 因爲不可能有優先級更低了的!
{
e.push_back(s.top());
s.pop();
}
s.push(str[i]);
}
else if(str[i] == "*" || str[i] == "/")
{
while(!s.empty() && s.top() != "(" && (s.top() == "*" || s.top() == "/")) //如果輸入的是"*"或"/",則只能處理棧中的*或/
{
e.push_back(s.top());
s.pop();
}
s.push(str[i]);
}
else
continue;
}
}
while(!s.empty()) //導出棧中的所有符號
{
e.push_back(s.top());
s.pop();
}
return e;
}
int main()
{
string str,a;
vector<string> zhongzhui,houzhui;
while(getline(cin,str))
{
if(str == "0")
break;
istringstream in(str);
while(in >> a)
zhongzhui.push_back(a);
houzhui = inToPostfix(zhongzhui);
cout.setf(ios::fixed);
cout.precision(2);
cout << evalPostFix(houzhui) << endl;
zhongzhui.clear();
houzhui.clear();
}
return 0;
}