c++純手工實現帶括號計算器(轉換成逆波蘭式計算)

目錄

課前預習:

 代碼實現過程:

1.先定義一下各運算符的優先級

2.轉化成逆波蘭式

3.計算逆波蘭式

測試結果:

刷題檢測網站

 

課前預習:

1.逆波蘭式的定義,如何將中綴表達式轉化成逆波蘭式

2.爲什麼要轉化成逆波蘭式,逆波蘭式有什麼優點

3.各運算符之間的優先級(+、-、*、/)

4.此計算器只支持輸入非負整數數,不支持輸入負數,要是非要輸入負數可以這樣(0-1)

 代碼實現過程:

1.先定義一下各運算符的優先級

解釋:左括號優先級最低,+-略高,*/較高,右括號最高

 
int priority(string op)
{
	if (op == "(") return 0;
	if (op == "+" || op == "-") return 1;
	else if (op == "*" || op == "/") return 2;
}

2.轉化成逆波蘭式

幾個關鍵的點

(1)碰到左括號直接進入符號棧

(2)右括號優先級最高,遇到右括號將符號棧中的運算符添加到逆波蘭式數組中,直到遇到左括號,並將左括號彈出

(3)當前爲運算符,如果棧頂的運算符優先級高於當前或等於(有些文章中將在符號棧中的運算符優先級看做高於棧外同類運算符,我這裏不這樣了,感覺還是我這樣簡單點)當前運算符,彈出棧頂運算符添加到逆波蘭式數組中(循環)

(4)最後如果符號棧非空,將符號棧中的元素彈出添加到逆波蘭式數組中


/*將表達式轉換成逆波蘭式*/
vector<string> toPolish(string str)
{
	stack<string> opstack;
	vector<string> polish;
	string str1;
	for (int i = 0; i < str.size(); i++)
	{
		if (str[i] == '(') /*左括號*/
		{
			opstack.push("(");
			continue;
		}
		if (str[i] >= '0'&&str[i] <= '9')/*數字*/
		{
			str1 = "";
			while (i < str.size() && str[i] >= '0'&&str[i] <= '9')
			{
				str1 += str[i];
				i++;
			}
			i--;
			polish.push_back(str1);
			continue;
		}
		 
		if (str[i] == ')')/*右括號*/
		{
			/*出棧,直到匹配到左括號*/
			while (!opstack.empty())
			{
				if(opstack.top() != "(")
				{
					polish.push_back(opstack.top());
					opstack.pop();
				}
				else
				{
					opstack.pop();
					break;
				}	
			}
			 
		}
		else/*加減乘除運算符*/
		{
			str1 = str[i];
			while (!opstack.empty() && priority(opstack.top()) >= priority(str1))
			{
					polish.push_back(opstack.top());
					opstack.pop();
			}
			opstack.push(str1); // 添加到符號棧中
		}
	}
	//剩餘的運算符添加到polish中
	while (!opstack.empty())
	{
		polish.push_back(opstack.top());
		opstack.pop();
	}
	return polish;
}

3.計算逆波蘭式

逆波蘭式有個大大的優點,就是符號沒有優先級,也就是說我們碰到運算符就進行運算,非常簡便

/*將逆波蘭式進行計算*/
int calculation(vector<string> polish)
{
	stack<int> data;
	int a, b, c;
	for (int i = 0; i < polish.size(); i++)
	{
		if (polish[i] == "+" || polish[i] == "-" || polish[i] == "*" || polish[i] == "/")
		{
			b = data.top(); data.pop();
			a = data.top(); data.pop();
			if (polish[i] == "+") c = a + b;
			else if (polish[i] == "-") c = a - b;
			else if (polish[i] == "*") c = a * b;
			else if (polish[i] == "/") c = a / b;
			data.push(c);
		}
		else
		{
			data.push(stoi(polish[i]));/*stoi函數功能:string to int */
		}
	}
	return data.top();
}

以上就是實現過程,下面就是全部代碼:

 
 #include <iostream>
#include<stack>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int priority(string op);
vector<string> toPolish(string str);
int calculation(vector<string> polish);
int main()
{
	string str = "1*(1+2*(1*2*2-3+5*1))";
	int a = calculation(toPolish(str));
	cout << a;
}

/*返回運算符的優先級*/
int priority(string op)
{
	if (op == "(") return 0;
	if (op == "+" || op == "-") return 1;
	else if (op == "*" || op == "/") return 2;
}

/*將表達式轉換成逆波蘭式*/
vector<string> toPolish(string str)
{
	stack<string> opstack;
	vector<string> polish;
	string str1;
	for (int i = 0; i < str.size(); i++)
	{
		if (str[i] == '(') /*左括號*/
		{
			opstack.push("(");
			continue;
		}
		if (str[i] >= '0'&&str[i] <= '9')/*數字*/
		{
			str1 = "";
			while (i < str.size() && str[i] >= '0'&&str[i] <= '9')
			{
				str1 += str[i];
				i++;
			}
			i--;
			polish.push_back(str1);
			continue;
		}
		 
		if (str[i] == ')')/*右括號*/
		{
			/*出棧,直到匹配到左括號*/
			while (!opstack.empty())
			{
				if(opstack.top() != "(")
				{
					polish.push_back(opstack.top());
					opstack.pop();
				}
				else
				{
					opstack.pop();
					break;
				}	
			}
			 
		}
		else/*加減乘除運算符*/
		{
			str1 = str[i];
			while (!opstack.empty() && priority(opstack.top()) >= priority(str1))
			{
					polish.push_back(opstack.top());
					opstack.pop();
			}
			opstack.push(str1); // 添加到符號棧中
		}
	}
	//剩餘的運算符添加到polish中
	while (!opstack.empty())
	{
		polish.push_back(opstack.top());
		opstack.pop();
	}
	return polish;
}
/*將逆波蘭式進行計算*/
int calculation(vector<string> polish)
{
	stack<int> data;
	int a, b, c;
	for (int i = 0; i < polish.size(); i++)
	{
		if (polish[i] == "+" || polish[i] == "-" || polish[i] == "*" || polish[i] == "/")
		{
			b = data.top(); data.pop();
			a = data.top(); data.pop();
			if (polish[i] == "+") c = a + b;
			else if (polish[i] == "-") c = a - b;
			else if (polish[i] == "*") c = a * b;
			else if (polish[i] == "/") c = a / b;
			data.push(c);
		}
		else
		{
			data.push(stoi(polish[i]));/*stoi函數功能:string to int */
		}
	}
	return data.top();
}

 

測試結果:

輸入:string str = "1*(1+2*(1*2*2-3+5*1))";

輸出:13

刷題檢測網站

如果想要練手,並檢驗是否正確,可以在Leetcode網站上檢測一下

leetcode-計算器

題目和我的代碼稍有不同  

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章