逆波兰算法(多位数运算)

【问题描述】
在计算机中,算术表达式由常量、变量、运算符和括号组成。由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。因而在程序设计时,借助栈实现。
【任务要求】
算法输入:一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示结束。
算法输出:表达式运算结果。
算法要点:设置运算符栈和运算数栈辅助分析算符优先关系。在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
问题分析
如果此类问题只需要计算10以内的数字运算,会非常简单。这里不再赘述。然而当需要计算多位数的计算时,例如123+(23-11)*113-45/3=?,当输入为字符串时,需要将表达式中运算数分离出来,并且利用负数代替其中的运算符。
本代码,借助《数据结构(C语言版)》(严蔚敏著)书中的53页算法,及其中关于运算符优先级的表格。

//2017 1 2 wangran  赵海航
//这个不能计算负数
//表达式中也不要出现0
#include<stdio.h>
#include<malloc.h>
#include<math.h>

float num[100]={0};
//使用-1,-2,-3,-4,-5,-6,-7,分别代表,+,-,*,/,(,),#
//使用-1,0,1分别代表<,=,>
int operate[8][8]={0, 0, 0, 0, 0, 0, 0, 0,//书p53表格
                   0, 1, 1,-1,-1,-1, 1, 1,
                   0, 1, 1,-1,-1,-1, 1, 1,
                   0, 1, 1, 1, 1,-1, 1, 1,
                   0, 1, 1, 1, 1,-1, 1, 1,
                   0,-1,-1,-1,-1,-1, 0, 0,
                   0, 1, 1, 1, 1, 0, 1, 1,
                   0,-1,-1,-1,-1,-1, 0, 0,
};

struct StackNode{
    float   data;
    struct StackNode *next;
};

struct LinkStack{
    struct StackNode *top;
    float   length;
};


struct LinkStack * InitStack ()//初始化栈结构
{
    struct LinkStack *S;
    S=(struct LinkStack *)malloc(sizeof(struct LinkStack));
    S->top=NULL;
    S->length=0;
    return S;
}

void Push(struct LinkStack * S,float  e)//入栈
{
    struct StackNode *p;
    p=(struct StackNode*)malloc(sizeof(struct StackNode));
    p->data=e;
    p->next=S->top;
    S->top=p;
    S->length++;
}

void   Pop(struct LinkStack *S)//出栈
{
    struct StackNode *p;
    p=(struct StackNode*)malloc(sizeof(struct StackNode));
    p=S->top;
    S->top=S->top->next;
    S->length--;
    free(p);
}

float  GetTop(struct LinkStack *S)//获得栈顶元素
{
    float e;
    e=S->top->data;
    return e;
}

int  StackEmpty(struct LinkStack *S)//判断是否为空栈
{
    return !(S->length);
}

void getnum()//将字符转化为整形数
{
    char c;
    int temp=0,temp2=0;
    int index=0;
    while((c=getchar())&&c!='\n')
    {
        if (isdigit(c))//如果是数字
        {
            temp=temp*10+(c-'0');
        }
        else
        {
          if (c=='+')
         {
            temp2=-1;
         }
         else if (c=='-')
         {
           temp2=-2;
         }
         else if (c=='*')
         {
            temp2=-3;
         }
         else if (c=='/')
         {
            temp2=-4;
         }
         else if (c=='(')
         {
          temp2=-5;
         }
         else if (c==')')
         {
           temp2=-6;
         }
         else if (c=='#')
         {
            temp2=-7;
         }
        }
        if (temp!=0&&temp2!=0)//此处我目前只想到这么写,
        {
            num[index++]=temp;
            num[index++]=temp2;
            temp=temp2=0;
        }
        else if (temp==0&&temp2!=0)
        {
            num[index++]=temp2;
            temp2=0;
        }

    }
}
int  precede(float  a,float  b)//获取a,b的优先级
{
    a=(int)(fabs(a));
    b=(int)(fabs(b));
    int n=a;
    int m=b;
    return operate[n][m];
}
float OPERATE(float  a,float  theta,float  b)//对于a,b操作
{
    switch((int)theta)
    {
        case -1:return a+b;
        case -2:return a-b;
        case -3:return a*b;
        case -4:return a/b;
    }
}

float  operandTypeEvaluateExperssion ()//计算函数,此算法使用使用书中53页
{
    int i=0,c;
    float  a,b,theta,x;
    struct LinkStack *OPTR,*OPND;
    OPTR=InitStack();
    OPND=InitStack();//初始化
    Push(OPTR,-7);
    c=num[i];
    while(c!=-7||GetTop(OPTR)!=-7)
    {
        if (c>=0)
        {
            Push(OPND,c);
            c=num[++i];
        }
        else
        {
            switch(precede(GetTop(OPTR),c))
            {
            case -1:
                Push(OPTR,c);
                c=num[++i];
                break;
            case 0:
                //Pop(OPTR,x);
                x=GetTop(OPTR);//这里由于不能使用引用操作,所以用gettop和pop代替书中的引用
                Pop(OPTR);
                c=num[++i];
                break;
            case 1:
                //Pop(OPTR,theta);
                theta=GetTop(OPTR);
                Pop(OPTR);
               // Pop(OPND,b);
                b=GetTop(OPND);
                Pop(OPND);
                //Pop(OPND,a);
                a=GetTop(OPND);
                Pop(OPND);

                Push(OPND,OPERATE(a,theta,b));
                break;

            }//switch
        }
    }//while
    return GetTop(OPND);
}

int main()
{
     getnum();
//     int i;
//     for (i=0;i<20;i++)
//        printf("%d ",num[i]);
     printf("\n结果为:%f\n",operandTypeEvaluateExperssion());
}

结果如图:
这里写图片描述
注:
此程序关键地方在于getnum()函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值