后缀表达式求值

题目要求:

后缀表达式求值:建立一个操作数栈S。然后从左到右读表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项操作数进行运算,再将运算的结果代替原栈顶的n项压入栈中。重复上面过程,如果后缀表达式读完且栈中只剩一个操作数,则该数就是运算结果;如果后缀表达式读完但是栈中操作数多于一个,则后缀表达式错误;如果栈中操作数只剩一个,但是后缀表达式还未读完且当前运算符为双元操作符,则后缀表达式同样错误。

输入格式:

在一行中输入一个以#号结束的非空后缀式,#不属于表达式的一部分,操作数和运算符都以空格分隔,运算数为绝对值不超过100的整数,运算符仅有+、-、*、/ 四种。

输出格式:

输出后缀式计算结果,所有的计算都只取结果的整数部分。题目保证计算的中间和最后结果的绝对值都不超过109。如果执行除法时出现分母为零的非法操作,则在一行中输出:Error: X/0,X是当时的分子。如果后缀表达式中运算符多了或者少了,则在一行中输出:Expression Error: X,X是当时栈顶元素。

输入样例1:5 -2 + 3 * # 输出:9

输入样例2:5 -2 2 + / # 输出:Error: 5/0

输入样例3:5 -1 3 + / - * # 输出Expression Error: 2

框架结构:

复制代码
//用于存放操作数的栈
int OPND[100];
int top=0;
//运算操作
int operate(int a,char operate,int b)
//计算表达式函数,如果出现错误的表达式返回false,表达式正确返回true,并且表达式的值最终会存在栈里。
bool caculate(string s);
int main()
{
	string s;
	top=0;
	getline(cin,s);//可以接受空格 
	if(caculate(s))
	{
		cout<<"表达式的值为:"<<OPND[0];                                                 
	}
}

栈的一些操作:

其实不用特意的写这些函数,下面几个操作都可以用一个语句完成,写成函数是为了方便阅读

复制代码
//栈的操作
void push(int num)
{
	OPND[top++]=num;
}
int pop()
{
	return OPND[--top];
}
int GetTop()
{
	return OPND[top-1];
}

将两个数进行一次操作的函数:

复制代码
int operate(int a,char operate,int b)
{//不出现/0的情况 
    int ans;
	if(operate=='+')
	    ans=a+b;
	else if(operate=='-')
	    ans=a-b;
	else if(operate=='*')
	    ans=a*b;
	else
	    ans=a/b;
	return ans;
}

计算表达式的函数:

我是一个字符一个字符扫描的,有的人习惯将表达式的string串以空格分成多个string串,对每个string串扫描,这样也可以。

复制代码
bool caculate(string s)
{
	int a,b,num=0,i=0;
	int sign=1;//记录数字符号 
	char thea;
	while(s[i]!='#')
	{
		if(s[i]>='0'&&s[i]<='9')
		{//遇到数字开始构造 
			num=10*num+s[i]-'0';
		}
		if(s[i]=='-'&&s[i+1]>='0'&&s[i+1]<='9')
		{//'-'后面跟着数字,说明遇到了负数 ,标记符号 
			sign=-1;
		}
		else if(s[i]=='+'||s[i]=='-'||s[i]=='/'||s[i]=='*')
		{
			if(top==0)
			{//没有操作数 
				cout<<"Expression Error: No operand!";
				return false;
			}
			else if(top<2)
			{//操作数不够 
				cout<<"Expression Error: "<<OPND[top-1];
				return false; 
			}
			b=pop();
			a=pop();
			if(b==0&&s[i]=='/')
			{//除数为零的情况 
				cout<<"Expression Error: "<<a<<"/"<<b;
				return false;
			}
			int ans=operate(a,s[i],b);//先抛出的做第二操作数
			push(ans); 
		}
		else if(s[i-1]>='0'&&s[i-1]<='9'&&s[i]==' ')
		{//当前字符是空格并且前面字符是数字 
			num*=sign;
			push(num);
			num=0;
			sign=1;
		}
		i++;
	}
	if(top>1)
	{//扫描结束后栈里的数大于一个,说明表达式有误
		cout<<"Expression Error: "<<OPND[top-1];
		return false;
	}
	return true;
}

代码:

复制代码
#include<iostream>
using namespace std;
int OPND[100];
int top=0;
//栈的操作
void push(int num)
{
	OPND[top++]=num;
}
int pop()
{
	return OPND[--top];
}
int GetTop()
{
	return OPND[top-1];
}
int operate(int a,char operate,int b)
{//不出现/0的情况 
    int ans;
	if(operate=='+')
	    ans=a+b;
	else if(operate=='-')
	    ans=a-b;
	else if(operate=='*')
	    ans=a*b;
	else
	    ans=a/b;
	return ans;
}
bool caculate(string s)
{
	int a,b,num=0,i=0;
	int sign=1;//记录数字符号 
	char thea;
	while(s[i]!='#')
	{
		if(s[i]>='0'&&s[i]<='9')
		{//遇到数字开始构造 
			num=10*num+s[i]-'0';
		}
		if(s[i]=='-'&&s[i+1]>='0'&&s[i+1]<='9')
		{//'-'后面跟着数字,说明遇到了负数 ,标记符号 
			sign=-1;
		}
		else if(s[i]=='+'||s[i]=='-'||s[i]=='/'||s[i]=='*')
		{
			if(top==0)
			{//没有操作数 
				cout<<"Expression Error: No operand!";
				return false;
			}
			else if(top<2)
			{//操作数不够 
				cout<<"Expression Error: "<<OPND[top-1];
				return false; 
			}
			b=pop();
			a=pop();
			if(b==0&&s[i]=='/')
			{//除数为零的情况 
				cout<<"Expression Error: "<<a<<"/"<<b;
				return false;
			}
			int ans=operate(a,s[i],b);//先抛出的做第二操作数
			push(ans); 
		}
		else if(s[i-1]>='0'&&s[i-1]<='9'&&s[i]==' ')
		{//当前字符是空格并且前面字符是数字 
			num*=sign;
			push(num);
			num=0;
			sign=1;
		}
		i++;
	}
	if(top>1)
	{
		cout<<"Expression Error: "<<OPND[top-1];
		return false;
	}
	return true;
}
int main()
{
	string s;
	top=0;
	getline(cin,s);//可以接受空格 
//	cout<<s;
	if(caculate(s))
	{
		cout<<"表达式的值为:"<<OPND[0];                                                 
	}
}
相关推荐
Sayuanni%36 分钟前
SpringBoot 从注解到源码:核心知识点总结
java·spring boot·后端
坚定信念,勇往无前30 分钟前
Maven 私有仓库-nexus
java
Minner-Scrapy37 分钟前
Scrapy 2.17 源码解析:Scheduler 调度器与磁盘/内存双队列
java·爬虫·python·scrapy·网络爬虫·twisted
晚风醉蝶1 小时前
1-11-奇偶排序-OddEvenSort
java·数据结构·算法
旖旎夜光1 小时前
LeetCode 852:山脉数组的峰顶索引(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
夏天拐跑了西瓜1 小时前
Spring Cloud 微服务实战(三):一个服务挂了,凭什么拖垮整个系统?Sentinel 限流熔断实战
java·spring cloud·微服务
CRMEB定制开发1 小时前
2026年最值得推荐的10大开源商城系统盘点
开发语言·人工智能·开源·商城系统·小程序商城
2601_967264281 小时前
Jetpack Compose 实践指南:从入门到进阶
java·学习
buhuizhiyuci2 小时前
【QT-百日筑基篇】修真世界摸爬滚打多年,终于黄天不负有心人,突破炼器中期——常用控件QWight的属性
开发语言·c++·qt·gui·图形化
m0_587383002 小时前
社区家政系统开发实战:从需求分析到上线部署全指南
java·spring boot·spring·需求分析