RPn обрабатывает отрицательное числовое деление

В настоящее время я делаю калькулятор, вводящий математическое выражение, и использую 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';
}

person Quang Huy    schedule 24.05.2018    source источник
comment
Этот код очень трудно прочитать.   -  person Eugene Sh.    schedule 24.05.2018
comment
Есть два способа обработки оператора отрицания. Либо считайте его частью числа, либо сохраните его в стеке RPn как другой символ, например #.   -  person user3386109    schedule 24.05.2018
comment
Я просто добавил несколько функций, которые использовал внутри infixToPostfix, чтобы сделать его более понятным.   -  person Quang Huy    schedule 24.05.2018
comment
Не забывайте, что вы можете вернуть условия. :)   -  person Gregoire Lodi    schedule 24.05.2018
comment
@user3386109 user3386109, когда я рассматривал его как число, добавляя условие (c>='-9' && c <='-1') к isNumber, результат деления 1/-1 равен -1, но 10/-10 также равен -10. Поскольку я оцениваю оператор, используя такое условие if (t[0] == '+') { c = a + b; }. Как я могу добавить условие #, как вы предлагаете?   -  person Quang Huy    schedule 24.05.2018
comment
Если ввод содержит - в начале выражения или сразу после другого оператора, измените символ на #. Получите следующее число и поместите его в стек RPn, затем поместите #. Когда код считывает # из выражения RPn, он должен извлечь число, инвертировать его и поместить обратно в стек.   -  person user3386109    schedule 24.05.2018
comment
Возможно, если за - следует цифра, это отрицание, иначе вычитание.   -  person chux - Reinstate Monica    schedule 24.05.2018
comment
Это разные операторы, как и в обычном калькуляторе (кнопка +/- против кнопки -). Унарный минус берет один операнд и инвертирует его. Двоичный минус принимает два операнда и вычитает их. Делайте все, что вам нужно, чтобы отличить их, это может быть так же просто, как пробел.   -  person Hans Passant    schedule 25.05.2018


Ответы (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, является операндом, закрывающей скобкой (любого вида) или знаком факториала, то это двоичный минус, иначе это должен быть унарный минус. То же самое с унарным плюсом.

Как только вы разметите оператор как унарный, его легко оценить, но вам нужно принять решение на основе типа оператора. Если это двоичный файл, дважды извлеките и примените бинарный оператор, если он унарный, извлеките один раз и примените оператор.

person phoxis    schedule 24.05.2018