鱼C论坛

 找回密码
 立即注册
查看: 1519|回复: 0

[技术交流] 一种改进的逆波兰计算器

[复制链接]
发表于 2020-3-17 15:53:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 代号-K 于 2020-3-17 16:56 编辑

听了小甲鱼的逆波兰算法,发现其中有很大的bug;
当要计算的算式 出现乘法与除法同时存在时,会出现转换错误,例如
1 + 2 - 3 * 4 / 5 * 6 会转换成 1 2 + 3 4 5 6 * / * - ,明显出现转换错误
解决方法:定义优先级 除法的优先级比乘法高一点

  1. #ifndef POLANDOPERATOR_H
  2. #define POLANDOPERATOR_H
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include "stack.h"
  7. #include <QHash>

  8. #define MAX_BUFF_VOLUMN 16

  9. template<class T>
  10. class PolandOperator
  11. {
  12. public:
  13.     PolandOperator(Stack<T> *S)
  14.     {
  15.         this->stack = S;
  16.         charHash.insert('+',0);
  17.         charHash.insert('-',0);
  18.         charHash.insert('*',1);
  19.         charHash.insert('/',2);
  20.         charHash.insert('^',3);
  21.     }

  22.     T getResult(char *buff)
  23.     {
  24.         char str[MAX_BUFF_VOLUMN] = {0};
  25.         char *p = buff;
  26.         int i = 0;
  27.         T d, e;
  28.         while(*p != '\0')
  29.         {
  30.             // filter digit
  31.             while(isdigit(*p) || *p == '.')
  32.             {
  33.                 str[i++] = *p;
  34.                 // use to end
  35.                 str[i] = '\0';
  36.                 if(i >=  MAX_BUFF_VOLUMN)
  37.                 {
  38.                     printf("error, this number is too big\n");
  39.                     return -1;
  40.                 }
  41.                 p++;
  42.                 //space
  43.                 if(*p == 32)
  44.                 {
  45.                     d = atof(str);
  46.                     stack->push(d);
  47.                     i = 0;
  48.                     break;
  49.                 }
  50.             }
  51.             switch (*p) {
  52.             case '+':
  53.                 stack->pop(&e);
  54.                 stack->pop(&d);
  55.                 stack->push(d+e);
  56.                 break;
  57.             case '-':
  58.                 stack->pop(&e);
  59.                 stack->pop(&d);
  60.                 stack->push(d-e);
  61.                 break;
  62.             case '*':
  63.                 stack->pop(&e);
  64.                 stack->pop(&d);
  65.                 stack->push(d*e);
  66.                 break;
  67.             case '/':
  68.                 stack->pop(&e);
  69.                 stack->pop(&d);
  70.                 if(e != 0)
  71.                 {
  72.                     stack->push(d/e);
  73.                 }
  74.                 else
  75.                 {
  76.                     printf("\n error, zero\n");
  77.                     return -1;
  78.                 }
  79.                 break;
  80.             case '^':
  81.                 stack->pop(&e);
  82.                 stack->pop(&d);
  83.                 stack->push((T)pow(d,e));
  84.                 break;
  85.             }
  86.             p++;
  87.         }
  88.         stack->pop(&d);
  89.         return d;
  90.     }

  91.     void getPolandExpression(char *buff, char *ret)
  92.     {
  93.         char*p = buff;
  94.         char e;
  95.         while(*p != '\0')
  96.         {
  97.             //digit
  98.             while((*p >= '0' && *p <= '9') || *p == '.')
  99.             {
  100.                 *ret++ = *p++;
  101.             }
  102.             *ret++ = 32;

  103.             // operator
  104.             charIter = charHash.find(*p);
  105.             if(charIter == charHash.end()){
  106.                 if('(' == *p) stack->push(*p);
  107.                 else if(')' == *p)
  108.                 {
  109.                     stack->pop(&e);
  110.                     while('(' != e)
  111.                     {
  112.                         *ret++ = e;
  113.                         *ret++ = 32;
  114.                         stack->pop(&e);
  115.                     }
  116.                 }
  117.             }else if(charIter != charHash.end()){
  118.                 //four operators
  119.                 if(!stack->stackLen()) stack->push(*p);
  120.                 else{
  121.                     do{
  122.                         stack->pop(&e);
  123.                         if('(' == e) stack->push(e);
  124.                         else{
  125.                             if(charIter.value() <= charHash.find(e).value()){
  126.                                 *ret++ = e;
  127.                                 *ret++ = 32;
  128.                             }else{
  129.                                 stack->push(e);
  130.                                 break;
  131.                             }
  132.                         }
  133.                     }while(stack->stackLen() && '(' != e);
  134.                     stack->push(*p);
  135.                 }
  136.             }
  137.             p++;
  138.         }
  139.         while (stack->stackLen()) {
  140.             stack->pop(&e);
  141.             *ret++ = e;
  142.             *ret++ = 32;
  143.         }
  144.         *ret = '\0';
  145.     }

  146. private:
  147.     Stack<T> *stack;
  148.     QHash<char, int> charHash;
  149.     QHash<char, int>::iterator charIter;
  150. };

  151. #endif // POLANDOPERATOR_H
复制代码


栈的实现
  1. #ifndef STACK_H
  2. #define STACK_H

  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stack>
  6. #define MAXSIZE 20
  7. #define STACKINCREMENT 10

  8. // define element type

  9. //typedef double ElemType;
  10. template<class T>
  11. struct Node
  12. {
  13.     T *base;
  14.     T *top;
  15.     int stackSize;
  16. };


  17. template<class T>
  18. class Stack
  19. {

  20. public:
  21.     Stack(struct Node<T> *S)
  22.     {
  23.         this->S = S;
  24.         initStack();
  25.     }
  26.     Stack(){}

  27.     void initStack()
  28.     {
  29.         S->base = (T *)malloc(MAXSIZE *sizeof(T));
  30.         if(!S->base)
  31.         {
  32.             printf("alloc failure\n");
  33.             exit(-1);
  34.         }
  35.         S->top = S->base;
  36.         S->stackSize = MAXSIZE;
  37.     }
  38.     void initStack(struct Node<T>*S)
  39.     {
  40.         this->S = S;
  41.         initStack();
  42.     }

  43.     void push(T e)
  44.     {
  45.         // stack is full
  46.         if((S->top) - (S->base) >= (S->stackSize))
  47.         {
  48.             S->base = (T*)realloc(S->base, (S->stackSize + STACKINCREMENT)*sizeof(T));
  49.             if(!S->base)
  50.             {
  51.                 printf("realloc failure\n");
  52.                 exit(-1);
  53.             }
  54.             S->top = (S->base) +(S->stackSize);
  55.             S->stackSize = S->stackSize + STACKINCREMENT;
  56.         }
  57.         *(S->top) = e;
  58.         S->top++;
  59.     }
  60.     void pop(T *e)
  61.     {
  62.         if(S->top == S->base)
  63.         {
  64.             printf("stack is empty\n");
  65.             return;
  66.         }
  67.         // top always point is empty, so must S->top--;
  68.         *e = *--(S->top);
  69.     }
  70.     int stackLen(void)
  71.     {
  72.         return (S->top-S->base);
  73.     }

  74. private:
  75.     struct Node<T> *S;
  76. };

  77. #endif // STACK_H
复制代码

  1. #include "stack.h"
  2. #include "polandoperator.h"

  3. typedef double Element;
  4. typedef char ConvertEle;
  5. int main(int argc, char *argv[])
  6. {
  7.     QCoreApplication a(argc, argv);

  8.     //convert polandExpression
  9.     char retArray[64] = {0};
  10.     char buff[32] = "2.4*3.6/2^2";
  11.     struct Node<ConvertEle> s1;
  12.     Stack<ConvertEle> stack1(&s1);
  13.     PolandOperator<ConvertEle> pld1(&stack1);
  14.     pld1.getPolandExpression(buff, retArray);
  15.     char *p = retArray;
  16.     while(*p != '\0')
  17.     {
  18.         printf("%c",*p);
  19.         p++;
  20.     }
  21.     printf("\n");

  22.     //computer polandExpression
  23.     struct Node<Element> s;
  24.     Stack<Element> stack(&s);
  25.     PolandOperator<Element> pld(&stack);
  26.     double ret = pld.getResult(retArray);
  27.     printf("%f\n", ret);
  28.     return 0;
  29. }
复制代码

实例的实现
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-23 15:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表