题目如下:
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如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