[数据结构]--PTA求前缀表达式的值

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。
输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、\以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR。
输入样例:
+ + 2 * 3 - 7 4 / 8 4
输出样例:
13.0
————————————
其实如果只是对于一位数就非常简单直接从后向前扫描即可,但是如果要满足两位数可以进栈,就有一点麻烦,需要判断有几位,再将其入栈,我这里用的是链栈,其实可以用顺序栈,就当做一个小小练习吧~
从后向前扫描,如果不是空格就要进行判断,判断有几位,如果是两位就存入临时的数组中,再利用反转(要吐槽这里不能使用库函数的strrev(),只好再重新写一个了。。。)和atof()函数将char[]转换为double类型,如果是一位直接入栈,如果是运算符就让两个数出栈,出栈前要判断是否为空(这里很容易出现错误的情况,如果空直接错误就退出就好~),之后直接进行运算,记得将运算结果入栈。
最后输出判断top的next是不是空就好,就是保证最后链栈只有一个元素,说明正确,其他情况不正确。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 30
//定义链栈
typedef struct snode
{
    double data;
    struct snode *next;
}StackNode,*LinkStack;
//置空栈
LinkStack top=NULL;
//入栈
LinkStack Push_LinkStack(double x)
{
    StackNode *p;
    p=(StackNode *)malloc(sizeof(StackNode));
    p->data=x;
    p->next=top;
    top=p;
    return top;
}
//出栈
double Pop_LinkStack()
{
    double x;
    StackNode *p;
    if(top==NULL) return 0;
    else{
    x=top->data;
    p=top;
    top=top->next;
    free(p);
    return x;
    }
}
//计算
double calcul(double a,double b,char c)
{
    switch(c)
    {
    case '+':
        return a+b;
    case '-':
        return b-a;
    case '*':
        return a*b;
    case '/':
        return b/a;
    default :
        return 0;
    }
}
//判栈空
int Empty_SeqStack()
{
    if(top==NULL)
        return 1;
    else
        return 0;
}
//字符串反转
char *revstr(char *str, int len)
{

    char    *start = str;
    char    *end = str + len - 1;
    char    ch;

    if (str != NULL)
    {
        while (start < end)
        {
            ch = *start;
            *start++ = *end;
            *end-- = ch;
        }
    }
    return str;
}
int main()
{
    char s[N];
    gets(s);
    char temp[N];
    char *strrevtemp;
    int i;
    int j=-1;
    double a,b,result;
    for(i=strlen(s)-1;i>=0;i--)
    {
        if(s[i]!=' ')
        {
            if(s[i-1]==' '||i==0)//判断下一位是不是空格
            {
                if(s[i]>='0'&&s[i]<='9')
                {
                     Push_LinkStack(s[i]-'0');
                     i--;
                }
                else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
                        if(!Empty_SeqStack())
                            a=Pop_LinkStack();
                        else{
                            printf("ERROR");
                            return 0;
                        }
                        if(!Empty_SeqStack())
                            b=Pop_LinkStack();
                        else{
                            printf("ERROR");
                            return 0;
                        }
                    if(s[i]=='/'&&b==0)
                    {
                        printf("ERROR");
                        return 0;
                    }
                    result=calcul(b,a,s[i]);
                    Push_LinkStack(result);
                }
                else{
                    printf("ERROR");
                    return 0;
                }
            }
            else{
                j=0;
                while(s[i]!=' '&&i>=0)
                    temp[j++]=s[i--];
                temp[j]='\0';
                if(strlen(temp)<=1)
                {
                    printf("ERROR");
                    return 0;
                }
                strrevtemp=revstr(temp,strlen(temp));
                Push_LinkStack(atof(strrevtemp));
                i++;

            }
        }
    }
        if(top!=NULL)
        printf("%.1lf",top->data);
        else
            printf("ERROR");
        return 0;
}
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值