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 toPolish(string str)
{
	stack opstack;
	vector 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 polish)
{
	stack 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 
#include
#include
#include
#include
using namespace std;
int priority(string op);
vector toPolish(string str);
int calculation(vector 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 toPolish(string str)
{
	stack opstack;
	vector 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 polish)
{
	stack 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-计算器

题目和我的代码稍有不同  

 

 

 

你可能感兴趣的:(C++&C)