7-65 求前缀表达式的值

题目如下:

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。

输入格式:

输入在一行内给出不超过30个字符的前缀表达式,只包含+-*/以及运算数,不同对象(运算数、运算符号)之间以空格分隔。

输出格式:

输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR

输入样例:

+ + 2 * 3 - 7 4 / 8 4

输出样例:

13.0

一开始思路比较直白,由右往左,一直遍历到开头,首先想到要设计一个字符串转化为数字的函数,设计了半天,没及时测试,结果卡了好久,大方向也有点问题,一开始用了两个栈;现在纠正过来了atof()函数即可自动转化,用函数递归,即可不需要用到栈了一下是本人自己设计的,略显简陋,不建议阅读:

#if 1 
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime> 
using namespace std;
const int N=10005;
char s0[N],s[N],n;
stack<float>S;
//计算前提(递推关系) 
//1.!S1.empty()&&S2.size()>=2
//2.if(S1.top()=='/')float f=S2.top;S2.pop();S2.top()!=0;S2.push(f);
float Cal(char c)
{
	float f1=0.0,f2=0.0;
	f1=S.top();
	S.pop();
	f2=S.top();
	S.pop();
	switch(c)
	{
		case '+':
			return f1+f2;
		case '-':
			return f1-f2;
		case '/':
			return f1/f2;
		case '*':
			return f1*f2;
	}
}
//判断正负号仅需问一下是否是长度为大于1,第一个字符为‘+’或‘-’ 即可
//判断是否有小数点,然后前取值后取值 
bool getnum(char *ptr,char &c,float &f,int l) 
{
	if(l>1)//囊括了正负号、小数,不包括一位数 
	{
		f=0;
		int t=0;
		while(t<l&&ptr[t++]!='.') ;
		float term=0.0;
		int plus=0;
		if(ptr[0]=='+')
			plus=1;
		else if(ptr[0]=='-')
			plus=-1;
		term=1;
		for(int i=(t<l? t-2:t-1);i>=(plus!=0? 1:0);i--)
		{
			f+=(ptr[i]-'0')*term;
			term*=10;
		}
		term=0.1;
		for(int i=t;i<l;i++)
		{
			f+=(ptr[i]-'0')*term;
			term*=0.1;
		}
		if(plus==-1)	f=-f;
		return true;
	}
	else if(ptr[0]<='9'&&ptr[0]>='0')
	{
		f=(ptr[0]-'0');
		return true;
	}
	else
	{
		c=ptr[0];
		return false;
	}
}
int main()
{
	freopen("in.txt","r",stdin);
	cin.getline(s,N);
	int l=strlen(s),i=l-1;
	//for(int i=0;i<l;i++)	s[i]=s0[l-i-1];//倒序的艰巨性: 
	//s[l]='\0';
	char *ptr=s+l-1;
	bool isok=true;
	while(i>=0)
	{
		int t=0;
		while(i+t>=0&&ptr[t--]!=' ');
		if(i+t<0)	ptr-=1;
		ptr+=t;
		i+=t;
		float f=0.0;
		char c='\0';
		if(getnum(ptr+2,c,f,-t-1))
		{
			//printf("%.0f\n",f);
			S.push(f);
		}
		else
		{
			//printf("%c\n",c);
			if(isok&&S.size()>1)
			{
				if(c=='/')
				{
					float f=S.top();
					S.pop();
					if(S.top()!=0)
						S.push(f);
					else
						isok=false;
				}
				if(isok)
				{
					float f=Cal(c);
					S.push(f);
				}
			}
			else
				isok=false;
		}
	}
	if(!isok||S.size()!=1)
		printf("ERROR\n");
	else
		printf("%.1f\n",S.top());
	return 0;
}
#endif
/*
https://www.cnblogs.com/zouhongmey/p/4280705.html
情况1:一位数四种运算 
+ + 2 * 3 - 7 4 / 8 4
输出1: 
13.0 	

情况2:有负数,两位整数 
/ -25 + * - 2 3 4 / 8 4
输出2: 
12.5

情况3:异常退出:1.不匹配	2.被除数为0 
/ 5 + * - 2 3 4 / 8 2	
输出3: 
ERROR

情况4:有正数符号 
+12.23
输出4: 
12.2
*/

至于优化后的代码,简明,清晰,直白,参考https://blog.csdn.net/linsheng9731/article/details/21615959

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值