【问题标题】:RPn handle negative number divisionRPn 处理负数除法
【发布时间】:2018-05-24 20:11:07
【问题描述】:

目前,我正在制作一个计算器,输入数学表达式并使用 RPn 进行计算。因此,我使用一个中缀到后缀的转换器函数来转换它。计算器通过将数字压入堆栈并检测运算符来工作。但是我的计算器有一个缺陷,它不能处理负数除法,例如 1/-1。我是否理解 RPn 错误或我对后缀函数的中缀有问题?

检测数字和运算符

int isOperator(char e){
    if(e == '+' || e == '-' || e == '*' || e == '/' || e == '^')
        return 1;
    else
        return 0;
}

int isNumber(char c) {
    if ((c>='0' && c<='9') || c=='.') {
        return 1;
    }
    return 0;
}

将数学表达式转换为后缀

void pushPostfix(struct postfixStack* s,int item){
    if(s->top == (100-1)){
        printf("\nSTACK FULL");
    }
    else{
        ++s->top;
        s->data[s->top]=item;
    }
}

char popPostfix(struct postfixStack* s){
    char a=(char)-1;
    if(!isEmpty(s)){
        a= s->data[s->top];
        --s->top;
    }
    return a;
}

void infixToPostfix(char* infix, char * postfix) {
    char *i, *p;
    struct postfixStack stack;
    char n1;
    emptyStack(&stack);
    i = &infix[0];
    p = &postfix[0];

    while (*i) {
        while (*i == ' ' || *i == '\t') {
            i++;
        }
        if (isNumber(*i)) {
            while (isNumber(*i)) {
                *p = *i;
                p++;
                i++;
            }
            *p = ' ';
            p++;
        }
        if (*i == '(') {
            pushPostfix(&stack, *i);
            i++;
        }
        if (*i == ')') {
            n1 = popPostfix(&stack);
            while (n1 != '(') {
                *p = n1;
                p++;
                *p = ' ';
                p++;
                n1 = popPostfix(&stack);
            }
            i++;
        }
        if (isOperator(*i)) {
            if (isEmpty(&stack)) {
                pushPostfix(&stack, *i);
            }
            else {
                n1 = popPostfix(&stack);
                while (priority(n1) >= priority(*i)) {
                    *p = n1;
                    p++;
                    *p = ' ';
                    p++;

                    n1 = popPostfix(&stack);
                }
                pushPostfix(&stack, n1);
                pushPostfix(&stack, *i);
            }
            i++;
        }
    }
    while (!isEmpty(&stack)) {
        n1 = popPostfix(&stack);
        *p = n1;
        p++;
        *p = ' ';
        p++;
    }
    *p = '\0';
}

【问题讨论】:

  • 这段代码很难阅读。
  • 有两种处理否定运算符的方法。要么将其视为数字的一部分,要么将其作为不同的字符存储在 RPn 堆栈中,例如 #
  • 我刚刚添加了一些我在infixToPostfix 中使用的函数以使其更清晰。
  • 别忘了可以返回条件。 :)
  • 这些是不同的运算符,就像它们在常规计算器上一样(+/- 按钮与 - 按钮)。一元减号取一个操作数并将其反转。二进制减法接受两个操作数并将它们相减。做任何你需要做的事情来区分它们,可以像空格一样简单。

标签: c calculator postfix-notation


【解决方案1】:

你可以考虑这样的事情。

   #define PLUS +
   #define MINUS - 
   #define UMINUS _
   #define DILIM_CLOSE 1
   #define DILIM_OPEN 0
   #define OPERAND 2
   #define FACT !

   // i is the present location being parsed in the infix string
   // infix is an array holding the infix string
   // this code can go to the tokeniser
   // optr_type returns the type of operator, or even if it is an operand

   if(infix[i]==PLUS || infix[i]==MINUS)
     {
         int sign=1,st=i;

         while(infix[i]==PLUS || infix[i]==MINUS)
             if(infix[i++]==MINUS)
                 sign*=-1;

         if(sign==-1)
         {

             if((optr_type(infix[st-1])==OPERAND) ||optr_type(infix[st-1])==DILIM_CLOSE || infix[st-1]==FACT)
                 return MINUS;

             else
                 return UMINUS;
         }

         if(sign==1)
         {
             if((optr_type(infix[st-1])==OPERAND) || optr_type(infix[st-1])==DILIM_CLOSE || infix[st-1]==FACT)
                 return PLUS;
             else
                 return UPLUS;
         }
     }

当您检测到在正负之后出现一连串负时,请继续翻转标志。如果是sign = -1,那么你用一个- 替换一连串的减号。例如--1 = 1---1 = -1。在sign == -1 条件中,如果st 中保存的前一个位置是操作数、右括号(任何类型)或阶乘符号,则它是二进制减号,否则它必须是一元减号。与一元加号相同。

一旦将运算符标记为一元,就很容易评估,但您需要根据运算符的类型来决定。如果是二元,则弹出两次并应用二元运算符,如果是一元,则弹出一次并应用运算符。

【讨论】:

    猜你喜欢
    • 2018-01-28
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多