利用栈来实现计算表达式的自动计算(一)

一、扫描两遍出结果的算法设置:
中缀变后缀:
(1): 设置一个运算符栈,初始化时将栈顶运算符设为 "#".
(2): 顺序扫描,当输入为操作数时就将其输出到后缀表达式。
(3): 当输入为运算符,则比较输入运算符和栈顶运算符的优先级。当输入运算符的优先级高于栈顶运算符的优先级时,则将其输入到运算符栈;若栈顶运算符的优先级高于输入的运算符的优先级,则将栈中的运算符弹出并输出到后缀表达式中,然后重新比较输入运算符和更新后的栈顶运算符的优先级的大小。
(4): 当输入运算符为 "(" 时,将 "(" 直接入栈。
(5): 当输入运算符为 ")" 时,将栈顶运算符出栈到后缀表达式,直至栈顶运算符为 "(" 时,将 "(" 出栈并抛弃,同时 ")" 也抛弃。
(6): 当扫描到 "#" 时,说明中缀表达式已经扫描完毕,将运算符栈依次出栈至后缀表达式直到栈顶为 "#" 时结束。
后缀计算:
(1): 设置一个用于存放操作数的栈。
(2): 顺序扫描后缀表达式,每读到一个数就将其入栈,每读到一个操作符就操作数栈中取出两个栈顶元素施以运算,并将结果作为新的操作数入栈。重复此操作直到后缀表达式读完。最后栈顶操作数即为后缀表达式的计算结果。 

二、扫描两遍出结果的源代码:

 

先把计算表达式变为后缀表达式,然后再进行计算。

#include <stdio.h>

#define StackSize 100

/* 定义字符栈 */

typedef char ElemType;

typedef struct

{

               

    ElemType  data[StackSize];

     int top;

}SqStack;

/* 定义数值栈 */

typedef struct{

           double  data[StackSize];

            int top;

}dstack;

/* 初始化数值栈 */

void  DsInit(dstack *s)

{

  s->top=-1;

}

/* 压栈 */

int Dpush(dstack *s,double e)

{

  if(s->top<StackSize-1)

  {

     s->top=s->top+1;/*若栈不满,则将e进栈*/

     s->data[s->top]=e;

     return 1;

  }

  else

  {

     return 0;

  }

}

/* 出栈 */

double Dpop(dstack *s)

{

  double e;

  if(-1==s->top)

  {

     return 1;

  }

  else

  {

     e=s->data[s->top];/*出栈*/

     (s->top)--;

     return e;

  }

}

/* 初始化字符栈 */

void  InitStack(SqStack *s)

{

    s->top=-1;

}

/* 压栈 */

int push(SqStack *s,ElemType e)

{

    if(s->top<StackSize-1)

    {

        s->top=s->top+1;

        s->data[s->top]=e;

        return 1;

    }

    else

    {

        return 0;

    }

}

/* 出栈 */

ElemType pop(SqStack *s)

{

    ElemType e;

    if(-1==s->top)

    {

        return 1;

    }

    else

    {

        e=s->data[s->top];

        (s->top)--;

        return e;

    }

}

/* 取栈顶 */

int GetTop(SqStack s,ElemType *e)

{

    if (0==s.top)

    {

          *e=s.data[s.top];

        return 0;

    }

    else

    {

        *e=s.data[s.top];

        return 1;

    }

}

/* 比较优先级 */

int Get_Pri(int mode,char oper)

{/* 返回运算符oper代表优先级得整数值,mode1,表示oper是栈顶运算符,否则是当前运算符 */

    int tmp;

    switch(oper)

    {

    case '#': tmp=0;break;

    case '(': tmp=(mode? 1:6);break;

    case '+':

    case '-': tmp=(mode? 3:2);break;

    case '*':

    case '%':

    case '/': tmp=(mode? 5:4);break;

    case ')': tmp=(mode? 7:1);break;

    }

    return tmp;

}

char precede(char w,char ch)

{/* 判定运算符栈的栈顶运算符w,与当前运算符ch之间的优先关系 */

    int grade;

    /* 取得栈顶运算符与当前运算符得优先级 */

    grade=Get_Pri(1,w)-Get_Pri(0,ch);

    if(grade>0)

        return '>';

    else

    {

        if(grade==0)

            return '=';

        else

            return '<';

    }

}

/* 中缀变后缀的实现函数 */

void change(char E[],char A[])

{

    SqStack S2;

    int i=0; /*i作为扫描数组E的指针*/

    int j=0;    /*j用来指示数组A中待写入字符的位置*/

    char ch=E[i];   /*E中第一个字符送给ch*/

    char w='/0';

    InitStack(&S2);

    push(&S2,'#');

    while (ch!='#')

    {

        if(ch>='0' && ch<='9'||ch=='.')

        {

            while(ch>='0' && ch<='9'||ch=='.')

            {

                A[j]=ch;

                j++;

                i++;

                ch=E[i];

            }

            A[j]=' ';

            j++;    /*A中的每个操作数后附加一个空格*/

        }

        if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%'||ch=='('||ch==')'||ch=='#')

        {

            GetTop(S2,&w);

            while (precede(w,ch)=='>')

            {

                A[j]=w;

                j=j+1;

                pop(&S2);

                GetTop(S2,&w);

            }

           if (precede(w,ch)=='<')

                push(&S2,ch);

            else

            {

                if(precede(w,ch)=='='&&w!='#')

                {

                    pop(&S2);

                    GetTop(S2,&w);

                }

            }

        }

        if(E[i]!='#')

            i++;

        ch=E[i];       

    }

    while(w!='#')

    {

        A[j]=w;

        j++;

        pop(&S2);

        GetTop(S2,&w);

    }

    A[j]='#';

    A[++j]='/0';

   

}

/* 计算后缀表达式的值 */

double comp(char arr[])

{

  dstack s;

  int i=0;

  char ch;

  double x=0,d=1.0;

  DsInit(&s);

  ch=arr[i];

  while(ch!='#')

  {

     switch(ch)

     {

         case '0':

         case '1':

         case '2':

         case '3':

         case '4':

         case '5':

         case '6':

         case '7':

         case '8':

         case '9':

         case '.':

            while(ch!=' ')

            {

                if('0'<=ch && ch<='9')

                {

                    while('0'<=ch && ch<='9')

                    {

                        x=x*10+(ch-'0');

                        i=i+1;

                        ch=arr[i];

                    }

                }

               

                else

                {

                    if(ch=='.')

                    {

                        ch=arr[++i];

                        while('0'<=ch && ch<='9')

                        {

                            d=d*10;

                            x=x+(ch-'0')/d;

                            ch=arr[++i];

                        }

                    }

                }

            }

            break;

         case '+':

            x=Dpop(&s)+Dpop(&s);

            break;

         case '-':

            x=Dpop(&s);

            x=Dpop(&s)-x;

            break;

         case '*':

            x=Dpop(&s)*Dpop(&s);

            break;

         case '/':

            x=Dpop(&s);

            x=Dpop(&s)/x;

            break;

         case '%':

            x=Dpop(&s);

            x=(double)((int)Dpop(&s)%(int)x);

            break;

   

     }

     Dpush(&s,x);

     x=0;

     i=i+1;

     ch=arr[i];

  }

  return Dpop(&s);

}

/* 主函数 */

void main()

{

    char E[100];

    char A[180];

    printf("Please input the infix express with a '#'in the end:");

    gets(E);

    change(E,A);

    printf("The surffix express is%s/n",A);

     printf("The result is%s=%f/n/n",E,comp(A));

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值