• 怎么实现Linux下的逆波兰计算器dc?


     #返回上一级

    @Author: 张海拔

    @Update: 2014-01-12

    @Link: http://www.cnblogs.com/zhanghaiba/p/3516660.html

      1 /*
      2  *Author: ZhangHaiba
      3  *Date: 2014-1-12
      4  *File: dc_linux.c
      5  *
      6  *a demo shows how to use a stack to implement dc which as a built-in tool in Linux
      7  *but, this demo only support int number and int operation + - * /
      8  */
      9 
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <ctype.h>
     13 #define ST_LEN 1024 //the depth of stack
     14 #define BUF_SIZE 32
     15 #define NUM '0'
     16 
     17 //public from stack.h
     18 void push(int);
     19 int pop();
     20 int top();
     21 int is_empty();
     22 int is_full();
     23 void clear();
     24 //private form stack.c
     25 int stack[ST_LEN];
     26 int sp = 0; //point to next empty space
     27 
     28 //public form main.h
     29 int token();
     30 //public form main.c
     31 char buf[BUF_SIZE];
     32 int cnt = 0;
     33 
     34 int main(void)
     35 {
     36     int c;
     37     int op2, op1;
     38     
     39     while ((c = token()) != EOF) {
     40         switch(c) {
     41         case NUM:
     42             push(atoi(buf));
     43             break;
     44         case '+':
     45             if (size() >= 2) {
     46                 op2 = pop(), op1 = pop();
     47                 push(op1 + op2);
     48             } else
     49                 printf("dc: stack empty
    ");
     50             break;
     51         case '-':
     52             if (size() >= 2) {
     53                 op2 = pop(), op1 = pop();
     54                 push(op1 - op2);
     55             } else
     56                 printf("dc: stack empty
    ");
     57             break;
     58         case '*':
     59             if (size() >= 2) {
     60                 op2 = pop(), op1 = pop();
     61                 push(op1 * op2);
     62             } else
     63                 printf("dc: stack empty
    ");
     64             break;
     65         case '/':
     66             if (size() >= 2) {
     67                 op2 = pop(), op1 = pop();
     68                 push(op1 / op2);
     69             } else
     70                 printf("dc: stack empty
    ");
     71             break;
     72         case 'p':
     73             printf(is_empty() ? "dc: stack empty
    " : "%d
    ", top());
     74         default:
     75             break;
     76         }
     77     }
     78     return 0;
     79 }
     80 
     81 int token()
     82 {
     83     int c = getchar();
     84     if (isdigit(c)) {
     85         buf[cnt++] = c;
     86         while ((c = getchar()) != EOF) {
     87             if (isdigit(c))
     88                 buf[cnt++] = c;
     89             else {
     90                 buf[cnt] = '';
     91                 cnt = 0;
     92                 ungetc(c, stdin);
     93                 return NUM;
     94             }
     95         }
     96     } else
     97         return c;
     98 }
     99 
    100 void push(int item)
    101 {
    102     if (!is_full())
    103         stack[sp++] = item;
    104 }
    105 
    106 int pop()
    107 {
    108     if (!is_empty())
    109         return stack[--sp];
    110 }
    111 
    112 int top()
    113 {
    114     if (!is_empty())
    115         return stack[sp-1];
    116 }
    117 
    118 int is_full()
    119 {
    120     return sp >= ST_LEN;
    121 }
    122 
    123 int is_empty()
    124 {
    125     return sp <= 0;
    126 }
    127 
    128 int size()
    129 {
    130     return sp;
    131 }
    132 
    133 void clear()
    134 {
    135     sp = 0;
    136 }

    Linux下有一个很强大计算器bc,而逆波兰计算器dc就是bc的后台。

    逆波兰表达式(后缀表达式)不需要括号也不需要定义优先级就可以运算,dc就是用来处理这种“干净”的输入。

    学习了栈这个数据结构,对于逆波兰表达式的计算是很容易的。

    规则是:遇到操作数则压栈,遇到操作符则弹栈,先后弹出两个操作数,第一个是op2,第二是op1,然后根据操作符把计算结果再次压栈。所以栈顶值就是当前计算的结果。

    这里的实现的简易dc,仅仅支持int整型,和int操作符+ - * /。

    dc的用例如下(上述实现的简易版 dc,其测试用例同下):

    432 13 * p
    5616
    3 p
    3
    * p
    16848
    * p
    dc: stack empty
    16848
    42 / 4 p
    4
    p
    4

    上面的实现中,需要注意的是:

    (1)数据封装方面,最好把stack做成一个单独模块,这样可以提供接口,隐藏stack数据本身。

    (2)对于栈中元素<2时遇到操作符,不要执行单独一次的弹栈(即把两次弹栈看做一个原子操作,测试发现dc就是这样处理的)。

    (3)由于输入数字不一定是一位数,所以需要一个buffer数组来存储多位数的字符表示并封装成字符串用标准库函数atoi转换,这个过程需要用ungetc(int, FILE*)来放回一个字符到缓冲区。

     #返回上一级

  • 相关阅读:
    20130118
    延迟加载、分页显示等功能的增加
    ==和Equals的区别
    20160115--Hibernate
    20160108--搜索查询
    20150105
    20151229--数据表格
    20151226--easyUI
    DreamWeaver使用技巧(转)
    20121109
  • 原文地址:https://www.cnblogs.com/zhanghaiba/p/3516660.html
Copyright © 2020-2023  润新知