C++实现中缀表达式转后缀

1.目的:

        实现中缀表达式转为后缀,并计算得到计算结果输出显示。

2.输入输出介绍:

        在英文输入下,键入你的表达式(注:这里只实现了 +-*/ 没有更复杂的幂次等计算)

之后,你将看到输出三部分:

        ①.将您输入的表达式的数字部分 和 操作符部分 分开,以独占一行的方式打印输出;

        ②.表达式的后缀输出;

        ③.计算结果。

        

3.完整代码,照例,无偿放在这里了:

/*
	1.要实现的目标是:根据输入的数学表达式,得到计算结果
	2.分析:
		数学表达式使用 字符串接受;
		从表达式中摘出来需要得到数字部分;
		需要两个栈
			字符串类型的;一个栈用于中缀表达式转后缀;一个在后缀计算结果时候用
*/

// 栈  先使用自定义实现;后面可以改成使用 STL容器

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<ctype.h>  // 当判断的字符是数字时,函数返回1~9的非零值,当判断的字符不是数字时,函数返回 0

// 自定义栈的数据结构
typedef struct lNode{
	string data;
	struct lNode* next;
}LNode, *LinkStack;

// 初始化  构造成不带头结点的
void init(LinkStack& s)
{
	s = NULL;
}

// 判空
bool isEmpty(LinkStack s)
{
	if (s == NULL)
		return true;
	else
	{
		return false;
	}
}
// 进栈操作  为了方便对栈顶的操作  这里使用 --- 新元素 指向 老元素 ---  的结构
void pushStack(LinkStack& s, string ele)
{
	LNode* newNode = new LNode;
	newNode->data = ele;
	newNode->next = s;

	s = newNode;		// 由于 要改变 栈顶指针的值  这里需要使用引用
}
// 出栈操作
void popStack(LinkStack& s, string& ret)
{
	if (isEmpty(s))
	{
		return;
	}
	ret = s->data;

	LNode* temp = s;
	s = s->next;

	delete temp;
}
// 读栈顶元素
string getTop(LinkStack s)
{
	if (!isEmpty(s))
	{
		return s->data;
	}
}
//销毁栈
void destroyStack(LinkStack& s)
{
	LNode* temp = s;
	while (temp != NULL)
	{
		LNode* nextNode = temp->next;
		delete temp;
		temp = nextNode;
	}

	s = NULL;  // 将外部栈指针置为 NULL
}

// 获取用户输入
string getExpression()
{
	string expression;
	cout << "请输入您的表达式,以回车结束" << endl;
	getline(cin, expression);

	return expression;
}

// 中缀转后缀
// 首先将 数字 与 +-*/ 操作符 区分出来,放入容器中,, 比如把 (32.1+2)*7/4  分成  (  32.1  +  2  )  *  7  /  4
vector<string> lookBetter(string expression)
{
	vector<string> vS;
	string str;
	for (auto c : expression)
	{
		if (isdigit(c) || c =='.')
		{
			str += c;
		}
		else
		{
			if (!str.empty())
			{
				vS.push_back(str);
				str.clear();
			}

			if (c == ' ')
			{
				// 跳过空格
				continue;
			}
			
			str = c;
			vS.push_back(str);
			str.clear();
		}
	}
	if (!str.empty())
	{
		vS.push_back(str);
		str.clear();
	}
	return vS;

}

// 判断字符串 是否可以转成小数
bool isNumber(const string& str)    // 使用 const 限定不能修改; 使用引用直接在本体上操作,不需要复制一份,提高性能
{
	try {
		stod(str);	// 字符串 转 double类型
		return true;
	}
	catch(const invalid_argument& e)
	{
		return false;
	}
	catch (const out_of_range& e)
	{
		return false;
	}
}

// 中缀表达式 转后缀
vector<string> mid2back(string expression)
{
	LinkStack S;
	init(S);

	vector<string> ret;

	vector<string> vS = lookBetter(expression);
	for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
	{
		if (isNumber(*itBegin))		// 如果是数字部分 直接放入后缀容器
		{
			ret.push_back(*itBegin);
		}
		else
		{
			// 这里用的 string 类型,需要使用双引号
			if ((*itBegin) == "(")   // 如果是"(" 直接入栈
			{
				pushStack(S, (*itBegin));
			}
			if ((*itBegin) == "+" || (*itBegin) == "-") // 如果是 "+"或"-"  将栈中遇到的所有+—*/ 出栈,,直到遇到第一个非 +—*/  ,,之后再将自己入栈
			{
				if (isEmpty(S))
					pushStack(S, (*itBegin));
				else
				{
					while (!isEmpty(S) && (getTop(S) == "+" || getTop(S) == "-" || getTop(S) == "*" || getTop(S) == "/"))
					{
						// 这里的非空判断是必要的  场景为 2+3-1  时  -将+出栈后,栈由非空变为空
						string popEle;
						popStack(S, popEle);
						ret.push_back(popEle);
					}
					pushStack(S, (*itBegin));
				}
			}
			if ((*itBegin) == "*" || (*itBegin) == "/") // 如果是 "*"或"/"  将栈中遇到的所有 */ 出栈,,直到遇到第一个非 */   ,,之后再将自己入栈
			{
				if (isEmpty(S))
					pushStack(S, (*itBegin));
				else
				{
					while (!isEmpty(S) && getTop(S) == "*" || getTop(S) == "/")
					{
						string popEle;
						popStack(S, popEle);
						ret.push_back(popEle);
					}
					pushStack(S, (*itBegin));
				}
			}
			if ((*itBegin) == ")")   // 如果是")" 将遇到的"("之前的所有元素出栈放入后缀容器中,  
			{
				string popEle;
				while (getTop(S) != "(")
				{
					popStack(S, popEle);
					ret.push_back(popEle);
				}
				popStack(S, popEle);  // 将"(" 出栈,不添加到 后缀容器中   ")"不入栈
			}
		}
	}

	// 最后 如果 栈内非空,将栈中元素 出栈
	while (!isEmpty(S))
	{
		string popEle;
		popStack(S, popEle);
		ret.push_back(popEle);
	}
	

	return ret;
}

// 计算后缀表达式 得到正确结果
double compute(vector<string> vS)
{
	LinkStack S2;
	init(S2);

	for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
	{
		if (isNumber(*itBegin))        // 如果是数字 直接入栈
		{
			pushStack(S2, *itBegin);
		}
		else
		{
			string leftValue;
			string rightValue;

			popStack(S2, rightValue);  // 先出栈的为右值
			popStack(S2, leftValue);

			if (*itBegin == "+")
			{
				double l = stod(leftValue);
				double r = stod(rightValue);
				pushStack(S2, to_string(l + r));
			}
			if (*itBegin == "-")
			{
				double l = stod(leftValue);
				double r = stod(rightValue);
				pushStack(S2, to_string(l - r));
			}

			if (*itBegin == "*")
			{
				double l = stod(leftValue);
				double r = stod(rightValue);
				pushStack(S2, to_string(l * r));
			}
			if (*itBegin == "/")
			{
				double l = stod(leftValue);
				double r = stod(rightValue);
				pushStack(S2, to_string(l / r));
			}
		}
	}

	if (!isEmpty(S2))
	{
		string ret;
		popStack(S2, ret);
		double retValue = stod(ret);

		return retValue;
	}
}


// 测试案例
void test()
{
	string expression = getExpression();
	vector<string> vS = lookBetter(expression);
	for (auto ele : vS)
	{
		cout << ele << endl;
	}
	cout << "----------------------" << endl;
	vector<string> mB = mid2back(expression);
	for (string ele : mB)
	{
		cout << ele<<"  ";
	}
	cout << endl << "----------------------" << endl;
	double value = compute(mB);

	cout << "计算结果是:" << value << endl;
}


int main()
{

	test();

	system("pause");
	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值