计算中缀表达式的值

输入:当一行中只有0 时输入结束,相应结果不输出。

分两步,一是将中缀转后缀,而是计算后缀表达式。

#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>
#include <map>
using namespace std;

struct node {
	double num; //操作数
	char op;  //操作符
	bool flag;  //true 表示操作数,false表示操作符 
};

string str;
stack<node> s;  //操作符栈
queue<node> q;  //用队列存放后缀表达式序列 
map<char, int> op;  //用于判断操作符优先级

void Change()  {
	double num;
	node temp;
	for(int i = 0; i < str.length(); ) {  //中缀转后缀 
		if(str[i] >= '0' && str[i] <= '9') { //如果是数字 
			temp.flag = true ;
			temp.num = str[i++] - '0';
			while(i < str.length() && str[i] >= '0' && str[i] <= '9') { //将操作数完整储存下来 
				temp.num = temp.num * 10 + (str[i] - '0');
				++i;
			}
			q.push(temp);  //操作数入队列 
		} else {
			temp.flag = false;  //是操作符
			//理论上来说,操作符的优先级分栈内栈外,观察发现,除括号外
			//操作符的栈内优先级均高于栈外优先级,而只有栈外优先级高于栈内时,入栈
			//同时乘除的优先级显然高于加减,因此将其简化,不分栈内栈外优先级
			//只要当前操作符栈顶的优先级低于当前操作符的优先级,就将栈顶出栈,入后缀表达式队列
			//最后栈内的操作符优先级必然小于当前操作符,再将当前操作符入栈即可 
			while(!s.empty() && op[str[i]] <= op[s.top().op]) {
				q.push(s.top());  //操作符栈顶元素入后缀表达式队列 
				s.pop();  //栈顶元素出栈 
			} 
			temp.op = str[i];
			s.push(temp);  //操作符入栈 
			++i;
		} 
		
	}
	//所有字符完成入栈,但是入队可能未完成 
	while(!s.empty()) {  //将栈内剩下的操作符入后缀表达式队列 
		q.push(s.top());
		s.pop();
	}
}

double Cal() {
	double temp1, temp2;
	node cur, temp;
	while(!q.empty()) {
		//只要后缀表达式队列非空
		cur = q.front();  //cur记录队列的队首元素
		q.pop(); //队首元素出队
		if(cur.flag == true) { //如果是操作数,将其入栈 
			s.push(cur) ;  //栈s之前是放操作符的,但是整理出后续表达式序列后,就没用了,如今废物利用 
		} else { //如果会操作符 
			temp2 = s.top().num;  //弹出第二操作数
			s.pop();
			temp1 = s.top().num;  //弹出第一操作数
			s.pop(); 
			temp.flag = true;
			if(cur.op == '+') {
				temp.num = temp1 + temp2;
			} else if(cur.op == '-'){
				temp.num = temp1 - temp2;
			} else if(cur.op == '*') {
				temp.num = temp1 * temp2;
			} else if(cur.op == '/') {
				temp.num = temp1 / temp2;
			}
			s.push(temp);  //结果入栈 
		}
	}
	return s.top().num;  //栈顶为结果 
}

int main() {
	op['+'] = op['-'] = 1;
	op['*'] = op['/'] = 2; //设置操作符优先级, 
	while(getline(cin, str), str != "0") {
		for(string::iterator it = str.end(); it != str.begin(); --it) {
			if(*it == ' ') {  //去掉多余的空格 
				str.erase(it);
			}
		}
		while(!s.empty()) {
			s.pop();  //初始化栈,清空栈 
		} 
		Change();
		printf("%.2lf", Cal()); 
	}
	
	return 0;
} ```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值