C++ 直接计算多项式的值

在数据结构上遇到了这个题...但是觉得麻烦没写,想想还是要学的,特此记录下来。

以下是代码:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <String>
#include <stack>
#include <cstdlib>
using namespace std;

/*
第一步,转换成后缀表达式
第二部,利用后缀表达式求解

如何转化为后缀表达式:

顺序扫描中序表达式
a) 是数字, 直接输出
b) 是运算符
i : “(” 直接入栈
ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
扫描完后, 将栈中剩余符号依次输出

*/
int main()
{
	string str_in;
	
	vector<string> houzhuibiaodashi;			//后缀表达式
	stack<char> CStack;
	string temp;			//临时
	stack <float> NStack;
	while (1)
	{
		houzhuibiaodashi.clear();			//后缀表达式向量清空
		while (!CStack.empty())				//运算符栈清空
		{
			CStack.pop();
		}
		temp = "";							//表达式清空
		while (!NStack.empty())				//数值栈清空
		{
			NStack.pop();
		}


		cout << "请输入多项式:";
		cin >> str_in;
		for (int i = 0; i < str_in.length(); i++)
		{

			if (str_in[i] >= '0' && str_in[i] <= '9')			//处理数字
			{
				temp = str_in[i];
				while (str_in[i + 1] >= '0' && str_in[i + 1] <= '9' && i<str_in.length())
				{
					temp += str_in[++i];
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式

			}

			else if ((str_in[i] == '-' && i == 0) || (str_in[i] == '-'&& str_in[i - 1] == '('))		//处理负数,不能处理-(3+2)这种
			{
				temp = "";

				temp = str_in[i++];
				while (str_in[i] >= '0' && str_in[i] <= '9' && i<str_in.length())
				{
					temp += str_in[i];
					i++;
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式
			}

			if (str_in[i] == '(')		//小括号直接入运算符栈
			{
				CStack.push(str_in[i]);				//运算符入栈
			}

			else if (str_in[i] == ')')
			{
				temp = "";
				while (!CStack.empty() && CStack.top() != '(')
				{
					temp = CStack.top();
					houzhuibiaodashi.push_back(temp);
					CStack.pop();
				}
				CStack.pop();			//(出栈
			}

			else if (str_in[i] == '+' || str_in[i] == '-' || str_in[i] == '*' || str_in[i] == '/')
			{
				temp = "";
				if (str_in[i] == '+' || str_in[i] == '-')
				{
					while (!CStack.empty() && (CStack.top() == '+' || CStack.top() == '-' || CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}
				else if (str_in[i] == '*' || str_in[i] == '/')
				{
					while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}

			}




		}


		while (!CStack.empty())
		{
			temp = CStack.top();
			CStack.pop();
			houzhuibiaodashi.push_back(temp);
		}


		/*完成后缀表达式,下边是李用后缀表达式求值*/

		

		int i = 0;
		float num1, num2;
		while (!houzhuibiaodashi.empty() && i<houzhuibiaodashi.size())
		{
			if (houzhuibiaodashi[i] == "+")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 + num2);
			}
			else if (houzhuibiaodashi[i] == "-")
			{
				if (i == 0)				//检测到负号时可能是负数
				{
					char * data = new char[houzhuibiaodashi.size()];
					for (int t = 1; t < houzhuibiaodashi[i].size(); t++)
					{
						data[t] = houzhuibiaodashi[i][t];
					}

					NStack.push(0 - atoi(data));
				}
				else
				{
					num1 = NStack.top();
					NStack.pop();
					num2 = NStack.top();
					NStack.pop();
					NStack.push(num2 - num1);
				}
			}
			else if (houzhuibiaodashi[i] == "*")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 * num2);
			}
			else if (houzhuibiaodashi[i] == "/")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 / num2);
			}
			else
			{
				char * data = new char[houzhuibiaodashi.size()];
				for (int t = 0; t < houzhuibiaodashi[i].size(); t++)
				{
					data[t] = houzhuibiaodashi[i][t];
				}

				NStack.push(atoi(data));
			}

			i++;
		}


		cout <<  "等式的值为" <<NStack.top() << endl;

	}
	

	system("pause");
}

更新后的代码:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <String>
#include <stack>
#include <cstdlib>
using namespace std;
/*
第一步,转换成后缀表达式
第二部,利用后缀表达式求解
如何转化为后缀表达式:
顺序扫描中序表达式
a) 是数字, 直接输出
b) 是运算符
i : “(” 直接入栈
ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
扫描完后, 将栈中剩余符号依次输出
*/
int main()
{
	string str_in;
	vector<string> houzhuibiaodashi;			//后缀表达式
	stack<char> CStack;
	string temp;			//临时
	stack <float> NStack;
	while (1)
	{
		houzhuibiaodashi.clear();			//后缀表达式向量清空
		while (!CStack.empty())				//运算符栈清空
		{
			CStack.pop();
		}
		temp = "";							//表达式清空
		while (!NStack.empty())				//数值栈清空
		{
			NStack.pop();
		}
		cout << "请输入多项式:";
		cin >> str_in;
		for (int i = 0; i < str_in.length(); i++)
		{
			if (str_in[i] == '(')		//小括号直接入运算符栈
			{
				CStack.push(str_in[i]);				//运算符入栈
			}
			else if (str_in[i] >= '0' && str_in[i] <= '9')			//处理数字
			{
				temp = str_in[i];
				while (str_in[i + 1] >= '0' && str_in[i + 1] <= '9' && i<str_in.length())
				{
					temp += str_in[++i];
				}
				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式
			}

			else if (
				(str_in[i] == '-'
				&&( i > 0 && !(str_in[i-1] >= '0' && str_in[i-1] <= '9'&& str_in[i + 1] >= '0' && str_in[i + 1] <= '9'))	//排除num-num型减法
				&&( i > 0 && !(str_in[i - 1] == ')' && str_in[i + 1] >= '0' && str_in[i + 1] <= '9'))	//排除()-num型减法
				&&( i > 0 && !(str_in[i + 1] == ')' && str_in[i - 1] >= '0' && str_in[i - 1] <= '9')))	//排除num-()型减法
				|| (str_in[i] == '-'&& i == 0)										//加入负数在多项式开头的情况
				)//处理负数,不能处理-(3+2)这种
			{
				temp = "";

				temp = str_in[i++];
				while (str_in[i] >= '0' && str_in[i] <= '9' && i<str_in.length())
				{
					temp += str_in[i];
					i++;
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式

				i--;			//防止指针过度移动。上一个版本的下一个分支直接用了if,不是else if , 虽然能解决这个问题但是不严谨

			}
			else if (str_in[i] == '-'&& str_in[i + 1] == '(' && (i == 0))		//处理-(3+2)在开头的多项式
			{
				

				houzhuibiaodashi.push_back("-1");			//改成-1 * (5+2) 进行计算,先压入-1,之后按照*规则处理


				while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
				{
					temp = "";
					temp = CStack.top();
					CStack.pop();
					houzhuibiaodashi.push_back(temp);
				}
				CStack.push('*');
			}

			

			else if (str_in[i] == ')')
			{
				temp = "";
				while (!CStack.empty() && CStack.top() != '(')
				{
					temp = "";
					temp = CStack.top();
					houzhuibiaodashi.push_back(temp);
					CStack.pop();
				}
				CStack.pop();			//(出栈
			}

			else if (str_in[i] == '+' || str_in[i] == '-' || str_in[i] == '*' || str_in[i] == '/')
			{
				temp = "";
				if (str_in[i] == '+' || str_in[i] == '-')
				{
					while (!CStack.empty() && (CStack.top() == '+' || CStack.top() == '-' || CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = "";
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}
				else if (str_in[i] == '*' || str_in[i] == '/')
				{
					while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = "";
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}

			}




		}


		while (!CStack.empty())
		{
			temp = CStack.top();
			CStack.pop();
			houzhuibiaodashi.push_back(temp);
		}


		/*完成后缀表达式,下边是李用后缀表达式求值*/

		

		int i = 0;
		float num1, num2;
		while (!houzhuibiaodashi.empty() && i<houzhuibiaodashi.size())
		{
			if (houzhuibiaodashi[i] == "+")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 + num2);
			}
			else if (houzhuibiaodashi[i] == "-")
			{
				if (i == 0)				//检测到负号时可能是负数
				{
					char * data = new char[houzhuibiaodashi.size()];
					for (int t = 1; t < houzhuibiaodashi[i].size(); t++)
					{
						data[t] = houzhuibiaodashi[i][t];
					}

					NStack.push(0 - atoi(data));
				}
				else
				{
					num1 = NStack.top();
					NStack.pop();
					num2 = NStack.top();
					NStack.pop();
					NStack.push(num2 - num1);
				}
			}
			else if (houzhuibiaodashi[i] == "*")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 * num2);
			}
			else if (houzhuibiaodashi[i] == "/")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num2 / num1);
			}
			else
			{
				char * data = new char[houzhuibiaodashi.size()];
				for (int t = 0; t < houzhuibiaodashi[i].size(); t++)
				{
					data[t] = houzhuibiaodashi[i][t];
				}

				NStack.push(atoi(data));
			}

			i++;
		}
		cout <<  "等式的值为" <<NStack.top() << endl;
	}
	system("pause");
}

代码更新说明:

上一个版本(就是划线的)简直bug百出,不能计算-(5+2)这种,除号和减号的运算规则也有错误。本次更新内容:

进一步优化判断条件;

修复了一些操作符bug;

完美支持加减乘除操作。

可自行加入乘方或者其他运算操作


第一步是将中缀表达式转换成后缀表达式。这一步很麻烦,用到的转换规则不是很好理解:

  1. 建立符号栈
  2. 顺序扫描中序表达式 
    a) 是数字, 直接输出 (即压入后缀表达式)
    b) 是运算符 
    i : “(” 直接入栈 (压入运算符栈CStack)
    ii : “)” 将符号栈中的元素依次出栈并输出(压入后缀表达式), 直到 “(“, “(“只出栈, 不输出 
    iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
  3. 扫描完后, 将栈中剩余符号依次输出

iii解释一下:举个例子,如果当前运算符栈中的内容是+,而当前的运算符是-,因为+不符合“比当前符号优先级低”的条件,所以需要将+弹栈并压入后缀表达式。之后栈为空,可以将-压入。也就是说,如果当前操作符是+、-,则一直弹栈,直到栈为空或者遇到“(”。如果当前操作符是*、/,则一直弹栈直到遇到+-或者“(”。


第二步是根据后缀表达式求值。很简单,从头读取后缀表达式,数字则压入数字栈,遇到操作符则从数字栈弹出相应数量数字进行运算(注意减法的减数和被减数不能搞错),运算结果压入数字栈。 最终,数字栈将只剩下一个数字,即为多项式运算结果。


附运行截图:



欢迎大家批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值