постфиксный оценщик не работает - PullRequest
0 голосов
/ 09 июня 2011

По какой-то причине, когда я запускаю эту программу со следующим выражением 12 12 * 66 +, она возвращает неверный и отрицательный ответ -46.Мне любопытно узнать, что происходит не так, и я хотел бы исправить это как можно скорее.

#include <stdio.h>
#include <stdlib.h>
#include "usefunc.h"
#define OFFSET '0'

/*
* I only use one constant.....I really don't need another. and in fact took more
* memory to use the constant than without. several bytes!!
*/

/*

* for this program, I found a library that contained C implementations
* of a stack. I thought I'd use it, since I understand everything it
* does fully. you can quiz me on the stuff I did not write, if you want.

*/

//setting up the stack
typedef char stackElementT;

//it's a struct, so it can contain several elements
//like maxSize, top, and of course the contents
//let's call it stackT
typedef struct {
  stackElementT *contents;
  int maxSize;
  int top;
  int min2;
} stackT;

//allocates the memory for the size passed to the function
//then checks if there's enough memory
//then sets the size to maxSize, `top` to -1 (empty), and contents to newContents
void StackInit(stackT *stackP, int maxSize) {
    stackElementT *newContents;
    newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize);
    if (newContents == NULL) {
        fprintf(stderr, "Not enough memory.\n");
        exit(1);
    }

    stackP->contents = newContents;
    stackP->maxSize = maxSize;
    stackP->top = -1; //empty...
}

//frees the allocated memory
//sets it all to NULL
//sets the size to 0, all that good stuff
void StackDestroy(stackT *stackP) {
    free(stackP->contents);
    stackP->contents = NULL;
    stackP->maxSize = 0;
    stackP->top = -1; //empty
}

//just referencing top
int StackIsEmpty(stackT *stackP) {
    return stackP->top < 0;
}

//and top again
int StackIsFull(stackT *stackP) {
    return stackP->top >= stackP->maxSize-1;
}

//and top once more
//adds one to the top of the stack by first incrementing the top, and then adding the element in at the top
//unless of course it's full
void StackPush(stackT *stackP, stackElementT element) {
    if(StackIsFull(stackP)) {
        fprintf(stderr, "Can't push element: stack is full.\n");
        exit(1);
    }
    stackP->contents[++stackP->top] = element;
}
//pops it, and then subsequently updates `top`
//unless of course it's empty
stackElementT StackPop(stackT *stackP) {
    if(StackIsEmpty(stackP)) {
        fprintf(stderr, "Can't pop element: stack is empty.\n");
        exit(1);
    }
    return stackP->contents[stackP->top--];
}

/*

* my work starts here:

*/

double eval(double x, double y, char operand) {
    switch(operand) {
        case '+': return x+y;
        case '-': return x-y;
        case '/': return x/y;
        case '*': return x*y;
        case '^': return pow(x, y);
    }
}

int is_operand(char x) {
    switch(x) {
        case '+':
        case '-':
        case '/':
        case '*':
        case '^': return 1;
        default: return 0;
    }
}

double postfix(char* expr, int length) {
    //counter, and two temporary variables
    int i;
    double temp = 0, temp2;
    //and of course the stack
    stackT stack;
    //lotta frames...
    StackInit(&stack, 1000);
    //loops through string input. as of now, it only works with one digit numbers :(
    for (i = 0; i < length; i++) {
        //printf("%d : %c\n", expr[i], expr[i]);
        //is it a number? yes? push the decimal version of it to the stack
        if ((expr[i] >= '0') && (expr[i] <= '9')) {
            //printf("temp=%f\n", temp);
            temp *= 10;
            temp += expr[i]-OFFSET;
            //printf("temp=%f\n", temp);
        }
        else if (expr[i] == ' ') {
            StackPush(&stack, temp);
            temp = 0;
        }

        //no?
        else {
            //switch-case statement, easy peasy
            switch (expr[i]) {
                //operations checking
                case '+': {
                    temp = StackPop(&stack);
                    temp2 = StackPop(&stack);
                    //printf("%f+%f\n", temp2, temp);
                    StackPush(&stack, temp2+temp);
                    temp = temp2+temp;
                }
                    break;
                case '-': {
                    temp = StackPop(&stack);
                    temp2 = StackPop(&stack);
                    //printf("%f-%f\n", temp2, temp);
                    StackPush(&stack, temp2-temp);
                    temp = temp2-temp;
                }
                    break;
                case '/': {
                    temp = StackPop(&stack);
                    temp2 = StackPop(&stack);
                    //printf("%f/%f\n", temp2, temp);
                    StackPush(&stack, temp2/temp);
                    temp = temp2/temp;
                }
                    break;
                case '*': {
                    temp = StackPop(&stack);
                    temp2 = StackPop(&stack);
                    //printf("%f*%f\n", temp2, temp);
                    StackPush(&stack, temp2*temp);
                    temp = temp2*temp;
                }
                    break;
                //POWERS?!?! whoa. this wasn't required.
                case '^': {
                    temp = StackPop(&stack);
                    temp2 = StackPop(&stack);
                    //printf("%f^%f\n", temp2, temp);
                    StackPush(&stack, pow(temp2, temp));
                    temp = pow(temp2, temp);
                }
                default:
                    break;
            }
        }
    }
    //just giving the number it pushed
    return StackPop(&stack);
}

int main() {
    //so many counters...!
    //almost a shell
    while (1) {
        //prompt
        printf("postfix expression:\t");
        //getLine
        char *expr = GetLine();
        //aaaaaaaaaand evaluate it
        printf("%.0f\n\n", postfix(expr, strlen(expr)));
    }
}

1 Ответ

2 голосов
/ 15 июня 2011

Проблема в том, что ваши элементы стека - это символы, которые, как кажется, подписаны на вашей платформе, а вы переходите вокруг SCHAR_MAX.

(12 * 12) +66 = 210. 210 для гексагона, для ясности, равен 0xd2. Однако интерпретация 0xd2 как значения со знаком, состоящего из двух символов, дает нам значение -46.

...