算术表达式的计算(基于逆波兰表达式)的c++实现

        以字符串的形式输入一个算术表达式,如何对其进行识别并计算出结果呢?

        如果按照普通的算术表达式计算,由于需要考虑到操作符和括号的优先级,实现起来十分麻烦。但是基于逆波兰表达式(也称后缀表达式)来计算的话,可以忽略其优先级顺序进行计算,十分简便。

        逆波兰表达式的定义及算法可以很方便的查询到,这里不再赘述。

        程序的说明如下:

        输入一个算术表达式,将其转换成为后缀表达式并输出计算结果。算术表达式中只能识别“+”、“-”、“*”、“/”四种运算符,负数需要用括号表示:如“(-1)”。对于除了操作数和运算符之外的字符自动忽略。

        首先是栈的定义以及字符串转换为长整形long的函数:

<span style="font-size:14px;">template<typename T>
class Stack {
public:
	void pop() {
		if (empty())
			return ;
		data.pop_back();
		--topstack;
	}
	const T& top() {
		return data[topstack];
	}
	void push(const T& item) {
		data.push_back(item);
		++topstack;
	}
	bool empty() {
		return topstack == -1 ? true : false;
	}

private:
	std::vector<T> data;
	int topstack = -1;
};

long str_to_num(const std::string& s) {  //字符串转长整形
	std::istringstream str(s);
	long num;
	str >> num;
	return num;
}
</span>


        程序实现的思路及代码如下:

        1.读取表达式,构造vector<string>储存成为普通的中缀表达式。忽略无意义字符,对于负数,去除括号保存。

<span style="font-size:14px;">void expression(std::vector<std::string> &vec ,const std::string& s){   
	std::string num;
	bool neg = false;               //判定是否负数
	for (auto iter = s.begin(); iter != s.end();/*空*/) {
		if (*iter >= 48 && 57 >= *iter) {
			num += *iter;
			++iter;
		}
		else if (*iter == '+' || *iter == '-' || *iter == '*' || *iter == '/') {
			if (num.size() != 0)
				vec.push_back(num);
			num = *iter;
			vec.push_back(num);
			num = "";
			++iter;
		}
		else if (*iter == '(') {                  //处理负数情况
			if (num.size() != 0) {
				vec.push_back(num);
				num = "";
			}
			if (*(++iter) == '-') {
				neg = true;
				num += '-';
				++iter;
			}
			else 
				vec.push_back("(");
		}
		else if (*iter == ')') {
			if (num.size() != 0) {
				vec.push_back(num);
				if (!neg)
					vec.push_back(")");
				num = "";
				++iter;
			}
		}
		else ++iter;
	}
	if (num.size() != 0)
		vec.push_back(num);
}</span>


        2.历遍中缀vector<string>,利用栈构造后缀vector<string>:

                  (1)对于操作数和左括号“(”,直接放入栈中。

                  (2)对于操作符“+”、“-”,弹出栈内元素直至栈为空或者遇到“(”,将操作符放入栈中。

            (3)对于操作符“*”、“/”,弹出栈内元素直至栈为空或者遇到“+”、“-”、“(”,将操作符放入栈中。
            (4)对于右括号“)”,弹出栈内元素直至遇到左括号“(”。
            (5)历遍结束后,弹出栈内所有元素。
<span style="font-size:14px;">void postfix_exp(std::vector<std::string> &p_vec, std::vector<std::string> &vec) {   
	Stack<std::string> sta;
	for (auto &oper : vec) {
		if (oper == "+" || oper == "-") {                    //对于加号和减号
			while (true) {
				if (sta.empty() || sta.top() == "(")
					break;
				p_vec.push_back(sta.top());
				sta.pop();
			}
			sta.push(oper);
		}
		else if (oper == "*" || oper == "/") {                //对于乘号和除号
			while (true) {
				if (sta.empty() || sta.top() == "+" ||
					sta.top() == "-" || sta.top() == "(")
					break;
				p_vec.push_back(sta.top());
				sta.pop();
			}
		    sta.push(oper);
		}
		else if (oper == ")") {                                  //对于右括号
			while (true) {
				if (sta.top() == "(") {
					sta.pop();
					break;
				}
				p_vec.push_back(sta.top());
				sta.pop();
			}
		}
		else sta.push(oper);
	}
	while (!sta.empty()) {
		p_vec.push_back(sta.top());
		sta.pop();
	}
	std::cout << "The postfix-expression is : ";
	for (auto &row : p_vec)
		std::cout << row<<" ";
	std::cout << std::endl;
}</span>


 3.历遍后缀vector<string>。对于操作数转换成为长整形long放入栈中;对于运算符则弹出两个操作数进行计算,然后将结果放入栈中。栈中剩余的最后一项便是计算的最终结果。
<span style="font-size:14px;">const long count(std::vector<std::string> &vec) {            
	Stack<long> sta;
	for (auto &oper : vec) {
		long lhs = 0, rhs = 0;
		if (oper=="+") {
			rhs = sta.top();
			sta.pop();
			lhs = sta.top();
			sta.pop();
			sta.push(lhs + rhs);
		}
		else if (oper == "-") {
			rhs = sta.top();
			sta.pop();
			lhs = sta.top();
			sta.pop();
			sta.push(lhs - rhs);
		}
		else if (oper == "*") {
			rhs = sta.top();
			sta.pop();
			lhs = sta.top();
			sta.pop();
			sta.push(lhs * rhs);
		}
		else if (oper == "/") {
			rhs = sta.top();
			sta.pop();
			lhs = sta.top();
			sta.pop();
			sta.push(lhs / rhs);
		}
		else
			sta.push(str_to_num(oper));
	}
	if (!sta.empty())
		return sta.top();
	else
		return 0;
}</span>

         最后则是main()函数的代码:
<span style="font-size:14px;">int main() {
	while (true) {
		std::string str;
		std::cout << "Enter the expression,or q for quit : ";
		std::cin >> str;
		if (str == "q")
			break;
		std::vector<std::string> exp;
		std::vector<std::string> p_exp;
		expression(exp, str);
		postfix_exp(p_exp, exp);
		std::cout << "The result is : " << count(p_exp) <<"."<< std::endl<<std::endl;
	}
}</span>
   新手一枚,欢迎大大们的建议和指导!



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值