C/C++ 编程—简单计算器 栈、队列、map

1918-ProblemA-简单计算器

题目描述
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

输入
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。

输出
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。

样例输入 Copy

30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
0

样例输出 Copy

12178.21

思路:
在这里插入图片描述
在这里插入图片描述

//1918-ProblemA-简单计算器--法2 
/*
中缀转后缀,计算后缀表达式 
步骤一:中缀表达式转后缀表达式
设立一个操作符栈,用以临时存放操作符,根据要求将符合要求的操作符从栈顶弹出到后缀表达式中;
设立一个数组或队列,用以存放后缀表达式。从左到右扫描中缀表达式,如果遇到操作数,
就把操作数加入后缀表达式中;如果遇到操作符,根据后缀表达式的特性,就将其操作符与操作符栈
的栈顶操作符的优先级比较:如果高于栈顶元素的优先级,则压入操作符栈;若低于或等于,则将操作符栈的栈顶元素不断弹出到后缀表达式中,
直到其优先级大于栈顶元素。重复以上操作,直到中缀表达式扫描完毕,之后将操作符栈剩余的操作符依次弹入到后缀表达式中。
步骤二: 计算后缀表达式
从左到右扫描后缀表达式,如果是操作数,则入栈;如果是操作符,则连续弹出两个操作数,
然后进行操作符的操作生成的新操作数压入栈中,直到后缀表达式扫描完毕,最终答案就是栈中最后一个元素。

*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <stack>
#include <map>
#include <string>
using namespace std;

struct node{
	double num;//数字 
	char op;//操作符 
	bool flag;//区分数字(1)操作符(0) 
}; 
string str;
stack<node> s;//操作符栈
queue<node> q;//后缀表达式队列
map<char,int> opp;//操作符优先级映射
void change(){//中缀表达式转后缀表达式
	double num;
	node temp;
	int len = str.length();
	for(int i=0;i<len; ){
		if(str[i] >= '0' && str[i] <= '9'){
			temp.flag = 1;
			temp.num = str[i++] - '0';//读取这个操作数的首位 
			while(i< len && str[i] >= '0' && str[i] <= '9'){//读取这个操作数 
				temp.num = temp.num * 10 + (str[i] - '0');
				i++;
			}
			q.push(temp);
		}
		else{//操作符 
			temp.flag = 0;
//若低于或等于,则将操作符栈的栈顶元素不断弹出到后缀表达式中,
//直到其优先级大于栈顶元素
			while(!s.empty() && opp[str[i]] <= opp[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 == 1)	s.push(cur);//操作数入栈
		else{//操作符
			temp2 = s.top().num;//弹出栈顶第一操作数
			s.pop();
			temp1 = s.top().num;//弹出第二操作数 
			s.pop();
			temp.flag = 1;//临时记录操作数
			if(cur.op == '+')	temp.num = temp1 + temp2;//加法
			else if(cur.op == '-')	temp.num = temp1 - temp2;
			else if(cur.op == '*')	temp.num = temp1 * temp2;
			else	temp.num = temp1 / temp2;
			s.push(temp);//将计算结果压入栈 
		} 
	}
	return s.top().num;//最终数字栈最后一个数即结果 
} 


int main() {
	opp['+'] = opp['-'] = 1;//设定操作符优先级
	opp['*'] = opp['/'] = 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\n",cal());//计算后缀表达式的值 
	} 
	return 0;
}

	

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隔壁de小刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值