• C语言 | 计算器实现(中缀表示法/后缀表示法)


    ————————————————————————————————————————————

    实现原理:

    每个操作数都被依次压入栈中,当一个运算符到达时,从栈中弹出相应数目的操作数(对于二元运算符来说是两个操作数),把该运算符作用于弹出的操作数,并把运算结果再压入栈中

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    计算器(后缀表达式)

    相关知识:

    后缀表达式(逆波兰表示法):在逆波兰中,所有运算符都跟在操作数后面,如下:(1 - 2) *(4 + 5) 采用逆波兰表示法表示为:1 2 - 4 5 + *,不需要圆括号,只要知道每个运算符需要几个操作数就不会引起歧义

    实现功能:

    输入后缀表达式,以换行结束,计算四则运算结果。

    对于 1 2 - 4 5 + * 来说,首先把1和2压入到栈中,再用两者之差-1取代它们;然后将4和5压入到栈中,再用两者之和9取代它们。最后从栈中取出栈顶的-1和9,并把它们的积-9压入到栈顶。到达输入行的末尾时,把栈顶的值弹出来并打印。

    伪代码:

    while 读入值不为换行时

    if 是数字

    压入栈中

    else if 是运算符

    弹出两个运算数,计算并压栈

    else 输入错误并退出

    end if

    读入值

    弹出最终结果并打印

    实现代码:

     

      1 /* 实现功能:输入后缀表达式,以换行结束,计算四则运算结果 */
      2 /* 这种后缀表示法只需要一个栈就可以了,遇到符号则弹运算数,但是中缀就不一样 */
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #define OK 1
      6 #define ERROR 0
      7 #define OVERFLOW -2
      8 #define STACK_INIT_SIZE 100
      9 #define STACKINCREAMENT 10
     10 typedef int Status;
     11 typedef char SElemType;
     12 typedef struct
     13 {
     14     SElemType *top;
     15     SElemType *base;
     16     int stacksize;
     17 } SqStack;
     18 Status InitStack(SqStack *s)
     19 {
     20     s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
     21     if (!s->base) exit(OVERFLOW);
     22     s->top = s->base;
     23     s->stacksize = STACK_INIT_SIZE;
     24     return OK;
     25 }
     26 Status Push(SqStack *s, SElemType e)
     27 {
     28     if (s->top - s->base == s->stacksize)
     29     {
     30         s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType));
     31         if (!s->base) exit(OVERFLOW);
     32         s->top = s->base + s->stacksize;
     33         s->stacksize += STACKINCREAMENT;
     34     }
     35     s->top++;
     36     *(s->top) = e;
     37     return OK;
     38 }
     39 Status Pop(SqStack *s, SElemType *e)
     40 {
     41     if (s->top == s->base) exit(OVERFLOW);
     42     *e = *(s->top);
     43     s->top--;
     44     return OK;
     45 }
     46 Status Empty(SqStack s)
     47 {
     48     if (s.top - s.base == 0)
     49         return OK;
     50     else
     51         return ERROR;
     52 }
     53 int main()
     54 {
     55     SqStack OPND; //OPTR是运算符 OPND是运算数
     56     char c, num1, num2;
     57     InitStack(&OPND);
     58     while((c = getchar()) != '
    ')
     59     {
     60         switch(c)
     61         {
     62         case '0':
     63         case '1':
     64         case '2':
     65         case '3':
     66         case '4':
     67         case '5':
     68         case '6':
     69         case '7':
     70         case '8':
     71         case '9':
     72             Push(&OPND, c - '0');
     73             break;
     74         case '+':
     75             Pop(&OPND, &num2);
     76             Pop(&OPND, &num1);
     77             Push(&OPND, num1 + num2);
     78             break;
     79         case '-':
     80             Pop(&OPND, &num2);
     81             Pop(&OPND, &num1);
     82             Push(&OPND, num1 - num2);
     83             break;
     84         case '*':
     85             Pop(&OPND, &num2);
     86             Pop(&OPND, &num1);
     87             Push(&OPND, num1 * num2);
     88             break;
     89         case '/':
     90             Pop(&OPND, &num2);
     91             Pop(&OPND, &num1);
     92             Push(&OPND, num1 / num2);
     93             break;
     94         default:
     95             break;
     96         }
     97     }
     98     while(!Empty(OPND))
     99     {
    100         Pop(&OPND, &c);
    101         printf("%d ", c);
    102     }
    103     return OK;
    104 }

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    计算器(中缀表示法)

    运算符优先级:

    +

    -

    *

    /

    (

    )

    #

    +

    >

    >

    <

    <

    <

    >

    >

    -

    >

    >

    <

    <

    <

    >

    >

    *

    >

    >

    >

    >

    <

    >

    >

    /

    >

    >

    >

    >

    <

    >

    >

    (

    <

    <

    <

    <

    <

    =

    0

    )

    >

    >

    >

    >

    0

    >

    >

    #

    <

    <

    <

    <

    <

    0

    =

    执行过程:

    在计算 #4+3*(5-10)/5# 时栈中的执行过程如下

    步骤

    输入字符

    执行操作

    OPTR

    OPND

    1

    #

    Push(#)

    #

      

    2

    4

    Push(4)

    #

    4

    3

    +

    '#'<'+',Push(+)

    # +

    4

    4

    3

    Push(3)

    # +

    4 3

    5

    *

    '+'<'*',Push(*)

    # + *

    4 3

    6

    (

    '*'<'(',Push(()

    # + * (

    4 3

    7

    5

    Push(5)

    # + * (

    4 3 5

    8

    -

    '('<'-',Push(-)

    # + * ( -

    4 3 5

    9

    10

    Push(10)

    # + * ( -

    4 3 5 10

    10

    )

    '-'>')',计算并压入结果

    # + * (

    4 3 -5

    11

      

    '('=')',脱括号

    # + *

    4 3 -5

    12

    /

    '*'>'/'计算并压入结果

    # +

    4 -15

    13

      

    '+'<'/',Push(/)

    # + /

    4 -15

    14

    5

    Push(5)

    # + /

    4 -15 5

    15

    #

    '/'>'#',计算并压入结果

    # +

    4 -3

    16

      

    '+'>'#',计算并压入结果

    #

    1

    17

      

    '#'='#',脱括号

      

    1

    伪代码:

    初始化运算符栈;压入#;

    初始化运算数栈;获取输入;

    while 获取输入不为#或栈顶不为#

    if 输入的是数字

    压入运算数栈

    获取输入

    if 新输入的也是数字

    十位数百位数运算

    end if

    else

    switch 运算符栈顶与当前输入优先级比较

    压入运算符栈

    获得输入

    弹出运算符栈顶(或#

    获得输入

    弹出运算符栈顶

    弹出两个运算数

    计算并将结果压入运算数栈

    //此时不获取新输入,该循环输入的运算符作为c重新进入循环

    end if

    end while

    输出运算数栈中剩的运算数

    实现代码:

     

      1 /* 只能运算-128~127之间的结果 */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <math.h>
      5 #define OK 1
      6 #define ERROR 0
      7 #define SPILL -2 //math.h中已有OVERFLOW,则改用SPILL
      8 #define STACK_INIT_SIZE 100
      9 #define STACKINCREAMENT 10
     10 typedef char SElemType;
     11 typedef int Status;
     12 typedef struct
     13 {
     14     SElemType *top;
     15     SElemType *base;
     16     int stacksize;
     17 } SqStack;
     18 Status InitStack(SqStack *s)
     19 {
     20     s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
     21     if (!s->base)
     22         exit(SPILL);
     23     s->top = s->base;
     24     s->stacksize = STACK_INIT_SIZE;
     25     return OK;
     26 }
     27 Status EmptyStack(SqStack s)
     28 {
     29     if (s.top - s.base == 0)
     30         return OK;
     31     else
     32         return ERROR;
     33 }
     34 Status Push(SqStack *s, SElemType e)
     35 {
     36     if (s->top - s->base == s->stacksize)
     37     {
     38         s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType));
     39         if (!s->base)
     40             exit(SPILL);
     41         s->top = s->base + s->stacksize;
     42         s->stacksize += STACKINCREAMENT;
     43     }
     44     s->top ++;
     45     *(s->top) = e;
     46     return OK;
     47 }
     48 Status Pop(SqStack *s, SElemType *e)
     49 {
     50     if (s->top == s->base)
     51         exit(SPILL);
     52     *e = *(s->top);
     53     s->top--;
     54     return OK;
     55 }
     56 SElemType GetTop(SqStack s)
     57 {
     58     return *(s.top);
     59     // *e = *(s.top);
     60     // return OK;
     61 }
     62 /* 判断如果是数字则返回OK,运算符返回ERROR,非法输入则退出 */
     63 Status InputJudge(SElemType c)
     64 {
     65     switch(c)
     66     {
     67     case '0':
     68     case '1':
     69     case '2':
     70     case '3':
     71     case '4':
     72     case '5':
     73     case '6':
     74     case '7':
     75     case '8':
     76     case '9':
     77         return OK;
     78         break;
     79     case '+':
     80     case '-':
     81     case '*':
     82     case '/':
     83     case '(':
     84     case ')':
     85     case '#':
     86         return ERROR;
     87         break;
     88     default:
     89         exit(SPILL);
     90         break;
     91     }
     92 }
     93 /* 当前输入的运算符和前一个运算符比较优先级 */
     94 SElemType PriorityJudge(SElemType optr1, SElemType optr2)
     95 {
     96     int i, j;
     97     char priorityTable[7][7] =
     98     {
     99         {'>', '>', '<', '<', '<', '>', '>'},
    100         {'>', '>', '<', '<', '<', '>', '>'},
    101         {'>', '>', '>', '>', '<', '>', '>'},
    102         {'>', '>', '>', '>', '<', '>', '>'},
    103         {'<', '<', '<', '<', '<', '=', '0'},
    104         {'>', '>', '>', '>', '0', '>', '>'},
    105         {'<', '<', '<', '<', '<', '0', '='}
    106     };
    107     switch(optr1)
    108     {
    109     case '+':
    110         i = 0;
    111         break;
    112     case '-':
    113         i = 1;
    114         break;
    115     case '*':
    116         i = 2;
    117         break;
    118     case '/':
    119         i = 3;
    120         break;
    121     case '(':
    122         i = 4;
    123         break;
    124     case ')':
    125         i = 5;
    126         break;
    127     case '#':
    128         i = 6;
    129         break;
    130     }
    131     switch(optr2)
    132     {
    133     case '+':
    134         j = 0;
    135         break;
    136     case '-':
    137         j = 1;
    138         break;
    139     case '*':
    140         j = 2;
    141         break;
    142     case '/':
    143         j = 3;
    144         break;
    145     case '(':
    146         j = 4;
    147         break;
    148     case ')':
    149         j = 5;
    150         break;
    151     case '#':
    152         j = 6;
    153         break;
    154     }
    155     return priorityTable[i][j];
    156 }
    157 /* 四则运算 */
    158 SElemType Calc(SElemType optr, SElemType num1, SElemType num2)
    159 {
    160     switch(optr)
    161     {
    162     case '+':
    163         return (num1 + num2);
    164         break;
    165     case '-':
    166         return (num1 - num2);
    167         break;
    168     case '*':
    169         return (num1 * num2);
    170         break;
    171     case '/':
    172         return (num1 / num2);
    173         break;
    174     }
    175 }
    176 int main()
    177 {
    178     char c, optr, num1, num2, temp;
    179     SqStack OPND, OPTR;
    180     InitStack(&OPTR);
    181     Push(&OPTR, '#');
    182     InitStack(&OPND);
    183     c = getchar();
    184     while(c != '#' || GetTop(OPTR) != '#')
    185     // while(!EmptyStack(OPTR))
    186     //严蔚敏老师书上的算法是判断输入非#或栈顶非#时循环,个人认为判断运算符栈不为空也可以,当初始化时压入的#闭合,结束运算
    187     {
    188         if (InputJudge(c))
    189         {
    190             Push(&OPND, c - '0');
    191             c = getchar();
    192             /* 当连续输入数字时,计算十位数和百位数 */
    193             while(InputJudge(c))
    194             {
    195                 int i = 1;
    196                 Pop(&OPND, &temp);
    197                 Push(&OPND, temp * pow(10, i) + (c - '0'));
    198                 i++;
    199                 c = getchar();
    200             }
    201         }
    202         else
    203             switch(PriorityJudge(GetTop(OPTR), c))
    204             {
    205             case '<':
    206                 Push(&OPTR, c);
    207                 c = getchar();
    208                 break;
    209             case '=':
    210                 Pop(&OPTR, &c);
    211                 c = getchar();
    212                 break;
    213             case '>':
    214                 Pop(&OPTR, &optr);
    215                 Pop(&OPND, &num2);
    216                 Pop(&OPND, &num1);
    217                 Push(&OPND, Calc(optr, num1, num2));
    218                 break;
    219             }
    220     }
    221     while(!EmptyStack(OPND))
    222     {
    223         Pop(&OPND, &c);
    224         printf("%d
    ", c);
    225     }
    226     return OK;
    227 }

     

     

  • 相关阅读:
    了解Cgroup资源配置方法
    了解Harbor私有仓库创建
    Docker私有部署和管理
    Docker构建镜像实例
    Docker镜像的构建方式
    Docker基本管理
    将列表的元素去重
    python打印出txt中的汉字
    join字符串拼接
    %s占位符 format
  • 原文地址:https://www.cnblogs.com/hughdong/p/6837247.html
Copyright © 2020-2023  润新知