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

来源:互联网 发布:我国的有限元软件 编辑:程序博客网 时间:2024/06/11 03:49

【问题描述】
在计算机中,算术表达式由常量、变量、运算符和括号组成。由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。因而在程序设计时,借助栈实现。
【任务要求】
算法输入:一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示结束。
算法输出:表达式运算结果。
算法要点:设置运算符栈和运算数栈辅助分析算符优先关系。在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
问题分析
如果此类问题只需要计算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()函数。

1 0
原创粉丝点击