1019.簡單計算器

題目描述:
讀入一個只包含 +, -, *, / 的非負整數計算表達式,計算該表達式的值。
輸入:
測試輸入包含若干測試用例,每個測試用例佔一行,每行不超過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;
}





發佈了63 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章