表达式求值

参考王道计算机机试指南

利用堆栈对表达式求值

1.设立两个堆栈,一个用于保存运算符,一个用于保存数字

2.在表达式的首位添加标记运算符,该运算符的优先级最低

3.从左至右遍历表达式,若遍历到运算符,则将该运算符与栈顶运算符进行比较,若栈顶运算符的优先级低或栈为空栈,则将运算符入栈。遍历字符串中的下一个元素

4.若栈顶运算符优先级大于当前遍历到的运算符的优先级,将运算符栈栈顶元素弹出栈,并从数字栈弹出两个数字,完成相应的运算后将结果压入数字栈,

5.若遍历到数字,则直接将数字压入数字栈

6.若运算符栈中只有两个元素,且栈顶元素为我们标记的运算符,那么表达式结束。数字栈中只有一个数字,就是我们要求的答案

#include <stack>
#include <stdio.h>

using namespace std;

char str[220];//保存表达式字符串
int mat[][5] = {//优先级矩阵,若mat[i][j]==1,则表示i号运算符优先级大于j号
				//运算符,运算编码规则为+为1号,-为2号,*为3号,/为4号,我们人为添加的为0号
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,0,
1,1,1,0,0,
1,1,1,0,0
};
stack<int> op;//运算栈符,保存运算符编号
stack<double> in;//数字栈
void getOp(bool &reto,int &retn,int &i)//获取表达式中下一个元素函数
{
	if(i == 0&&op.empty() == true||str[i] == 0)//若此时遍历字符串第一个字符,且运算栈为空,我们人为添加编号为0的标记字符
	{
		reto = true;//为运算符
		retn = 0;//编号为0的标记字符
		return;//返回
	}
	if(str[i]>='0'&&str[i]<='9')
	{
		reto = false;//返回为数字
	}
	else
	{
		reto = true;//返回为运算符
		if(str[i]=='+')
		{
			retn = 1;
		}
		else if(str[i] == '-')
		{
			retn = 2;
		}
		else if(str[i] == '*')
		{
			retn = 3;
		}
		else if(str[i] == '/')
		{
			retn = 4;
		}
		i +=2;//i递增,跳过该运算符和该运算符后的空格
		return;
	}
	retn = 0;//返回结果为数字
	for(;str[i]!= ' '&&str[i]!=0;i++)//计算该数字的数字值
	{
		retn +=10;
		retn +=str[i]-'0';
	}
	if(str[i] ==' ')//若其后字符为空格,则表示字符串未被遍历完
		i++;
	return;
}
int main()
{
	while(gets(str))
	{
		if(str[0] == '0'&&str[1] == 0)//若输入只有一个0,则退出
			break;
		bool retop;
		int retnum;
		int idx = 0;//定义遍历到的字符串下标,初始值为0
		while(!op.empty())
			op.pop();
		while(!in.empty())
			in.pop();
		while(true)		//循环遍历表达式字符串
		{
			getOp(retop,retnum,idx);
			if(retop == false)//若该元素为数字
			{
				in.push((double)retnum);
			}
			else
			{
				double tmp;
				if(op.empty()==true||mat[retnum][op.top()]==1)
				{
					op.push(retnum);
				}
				else
				{
					while(mat[retnum][op.top()] == 0)
					{
						int ret = op.top();
						op.pop();
						double b = in.top();
						in.pop();
						double a = in.top();
						in.pop();
						if(ret == 1)
							tmp = a+b;
						else if(ret == 2)
							tmp = a-b;
						else if(ret == 3)
							tmp = a*b;
						else
							tmp = a/b;
						in.push(tmp);
					}
					op.push(retnum);	//将当前运算符压入运算符堆栈
				}
			}
			if(op.size() == 2&&op.top() == 0)//若运算符堆栈只有两个元素,且其栈顶元素为标记运算符,则表达式求值结束
				break;
		}
		printf("%.2f\n",in.top());//输出数字栈中唯一的数字
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值