Инфиксный калькулятор

Im writting a program (this is homework) to create an infix calculator in C using stacks. i came up with the following logic :

  • have two stacks : one for numbers , one for operators.
  • store input as a char string and then scan one char at a time , pushing each element into its proper stack.
  • ignore open parens , on encountering a closed paren : pop two numbers from numstack , and one operator from the opstack , calculate based on the popped values , and return the the answer.

    пример: (1+(2*3)) должно дать 7

    но он не работает. я получаю мусор в качестве вывода. это мой результат:

    enter string to be evaluated (100 chars max): (1+1)
    
    string : (1+1)
    Length : 5
     reading : (
     reading : 1  pushing : 1
     reading : +  pushing : 43
     reading : 1  pushing : 1
     reading : )  popping : 1 popping : 1 popping : 431 + 302 = 303
     pushing : 303
    

    я не понимаю почему. некоторая помощь была бы здоровой.


    мой код:

    #include<stdio.h>
    #include<conio.h> // i **have to** use turbo c.
    #define LEN 25
    
    void push(int *stack  , int* top ,int item){
        printf(" pushing : %d ", item);
        stack[*top] = item;
        (*top)++;
    }
    
    int pop(int *stack , int* top){
        int temp;
        (*top)--;
        temp = stack[*top];
        printf(" popping : %d",temp); // this causing a dilemma while popping character operators.
        return temp;
    }
    
    void calc(int* numstack , int* numtop, int* opstack , int* optop){
        int num1,num2,ans;
        char sign;
    
        num1 = pop(numstack,numtop);
        num1 = pop(numstack,numtop);
    
        switch(pop(opstack,optop)){
            case '+' : ans = num1 + num2; sign = '+' ; break;
            case '-' : ans = num1 - num2; sign = '-' ; break;
            case '*' : ans = num1 * num2; sign = '*' ; break;
            case '/' : ans = num1 / num2; sign = '/' ; break;
        }
        printf("%d %c %d = %d \n",num1,sign,num2,ans);
        push(numstack,numtop,ans);
        while(getchar()!='\n'){} // cleanup stdin from any junk
    }
    
    int main(void){
        int optop = 0 , numtop = 0, i=0 , numstack[50] , opstack[30];
        char str[102], c;
        clrscr();
    
        // read and trim input evaluatioon string
        printf("enter string to be evaluated (100 chars max): ");
        fgets(str , 100 , stdin);
        while(str[i]!='\n'){ i++; }
        str[i] = '\0';
        printf("\nstring : %s \nLength : %d",str,i);
    
        i = 0;
        // evaluate
        while( (c=str[i]) !='\0'){
        printf("\n reading : %c ",str[i]);
        if(c=='('){ i++; continue; } // ignore open parens
        else if(c=='+'||c=='-'||c=='*'||c=='/') push(opstack,&optop,c);
        else if(c>=48 && c <=57) push(numstack,&numtop,(c-48));
        else if(c==')') calc(numstack , &numtop, opstack , &optop);
        else printf("\n%c is invalid..\n",c);
        i++;
        }
        printf("\nanswer is : %g",pop(numstack,&numtop));
        getch(); // again , *must use* turbo c
        return 0;
    }
    

  • person Somjit    schedule 20.12.2013    source источник
    comment
    извините .. кнопка публикации была нажата раньше, чем я хотел. обновил запрос.   -  person Somjit    schedule 20.12.2013
    comment
    Найдите обратную польскую нотацию — см. en.wikipedia.org/wiki/Reverse_Polish_notation. Существуют алгоритмы преобразования в него из инфиксной записи   -  person Ed Heal    schedule 20.12.2013
    comment
    Вы пытались использовать отладчик, чтобы увидеть, откуда берется мусор?   -  person Barmar    schedule 20.12.2013
    comment
    Тьфу, хардкодинг 48 и 57. Пожалуйста, используйте c >= '0' && c < '9'.   -  person Barmar    schedule 20.12.2013
    comment
    нет. Я не знаю, как. я думал, что это будет простая ошибка, которую я не замечаю, поэтому я написал здесь.   -  person Somjit    schedule 20.12.2013
    comment
    Когда я пытаюсь скомпилировать ваш код, я получаю: calc.c:58: предупреждение: формат '%g' ожидает тип 'double', но аргумент 2 имеет тип 'int'   -  person Barmar    schedule 20.12.2013
    comment
    спасибо бармар. по-видимому, turbo c не показывает эту ошибку. больше причин не любить это .. (до сих пор я застрял с этим.) я попробую то, что вы сказали.   -  person Somjit    schedule 20.12.2013
    comment
    отредактировал мой код, чтобы включить вывод для простого случая.   -  person Somjit    schedule 20.12.2013
    comment
    Второстепенный: читать 100 символов + \n + \0: fgets(str , sizeof(str) , stdin); (c>='0' && c <='9') более осмысленно и переносимо.   -  person chux - Reinstate Monica    schedule 20.12.2013
    comment
    Игнорировать открытые скобки явно неправильно, так как 1*(2+3) и (1*2+3) будут обрабатываться одинаково. Существует обширная литература о том, как анализировать выражения с использованием стека операторов и стека операндов ... вы должны изучить это. Обратите внимание, что в вашем примере (1+(2*3)) скобки вообще не нужны, что делает его очень плохим примером.   -  person Jim Balter    schedule 20.12.2013


    Ответы (1)


    Вот ваша проблема:

    num1 = pop(numstack,numtop);
    num1 = pop(numstack,numtop);
    

    Вы назначаете num1 оба раза, первый должен быть num2.

    Вам также необходимо изменить окончательную строку ответа на:

    printf("\nanswer is : %d\n",pop(numstack,&numtop));
    

    %g для двойных, %d для целых.

    person Barmar    schedule 20.12.2013
    comment
    отличные глаза! большое спасибо. совсем пропустил. Кроме того, я хотел бы отметить здесь, что в отличие от современных компиляторов, turbo c не выдает никаких ошибок при несоответствии %d-%g. похоже, что он просто не выполняет эту строку кода (printf в моем случае). просто чувствовал, что я дам людям знать. - person Somjit; 20.12.2013
    comment
    Это было довольно ясно из того факта, что он сказал одно число в popping: и другое число, когда распечатал расчет. - person Barmar; 20.12.2013
    comment
    @SomjitNag Это не столько большие глаза, сколько опыт, как шахматисты смотрят на доску и видят позицию, тогда как не шахматисты смотрят на доску и видят беспорядок фигур. - person Jim Balter; 20.12.2013
    comment
    Меня это не зацепило, мне пришлось запустить программу несколько раз и посмотреть на вывод, чтобы увидеть, что не имеет смысла, а затем вернуться оттуда. Я видел, что он напечатал popping : 1 popping: 3, но затем написал 1 + 302 = 303. Поэтому я задался вопросом, почему num2 был установлен на 303, когда он должен был быть 3, вернулся назад, и тогда я это увидел. - person Barmar; 20.12.2013