Оценка выражения с использованием стека (C) - PullRequest
0 голосов
/ 24 октября 2018

Мне нужно сделать стек, который будет вычислять выражение так же, как в ракетке.Вот пример рабочего вывода:

Please enter the racket expression to be evaluated: 
(+ 3 (* 2 20))
+--TOP OF STACK--+
|       20        |
==================

+--TOP OF STACK--+
|       2        |
|       20        |
==================

+--TOP OF STACK--+
|       40        |
==================

+--TOP OF STACK--+
|       3        |
|       40        |
==================

+--TOP OF STACK--+
|       43        |
==================

The result is: 43

Would you like to enter another expression (Y/N)?

В этом случае моя функция pop работает нормально и так, как задумано.Когда я делаю выражение немного сложнее, хотя функция pop перестает работать.Я запутался, почему, хотя, потому что он использует тот же код.Вот пример вывода, в котором функция pop не работает:

Please enter the racket expression to be evaluated: 
(+ (*2 4) (+ 10 2))
+--TOP OF STACK--+
|       2        |
==================

+--TOP OF STACK--+
|       10        |
|       2        |
==================

+--TOP OF STACK--+
|       12        |
==================

+--TOP OF STACK--+
|       4        |
|       12        |
==================

+--TOP OF STACK--+
|       2        |
|       4        |
|       12        |
==================

+--TOP OF STACK--+
|       8        |
|       2        |
|       4        |
|       12        |
==================

+--TOP OF STACK--+
|       10        |
|       8        |
|       2        |
|       4        |
|       12        |
==================

The result is: 10

Would you like to enter another expression (Y/N)?

Она отлично работает для (+ 10 2) части выражения, а 10 и 2 отображаются как и ожидалось.Затем 4 и 2 выталкиваются, как и ожидалось, но когда они выталкиваются, они не выталкиваются из стека, а правильное число 8 выталкивается, поэтому я знаю, что была вызвана функция pop.Я прошел и стек выглядит нормально, пока не дойдет до той точки, где по какой-то причине вызывается pop, но он не удаляет старые цифры, просто возвращает их значение.

Вот моя функция pop:

int pop(Node** top)
{
    int pop = (*top)->digit; //stores the value to be returned.
    *top = (*top)->prev; //"pops" the top element off the stack.

    return pop; //returns the digit as an integer
}

Вот функция толчка:

void push(Node** stackEnd, int digit)
{
    Node* ptr = *stackEnd;        // used to traverse the list

    // set up new node
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->prev = NULL;
    newNode->digit = digit;
    newNode->next = NULL;

    // add node to linked list
    if (*stackEnd == NULL)
            *stackEnd = newNode;           // first node in list
    else
    {
            // find the end of the list
            while (ptr->next != NULL)
                    ptr = ptr->next;

            // update pointers
            ptr->next = newNode;
            newNode->prev = ptr;
    }

    // assign new endPtr
    *stackEnd = newNode;
}

, и вот та часть в основном, которую я считаю уместной.Pop вызывается в операторе else внизу, когда найден оператор:

Node* startPtr = NULL;      //nodes for linked list that will be used for the expression
    Node* endPtr = NULL;
    Node* stackEnd = NULL;      //node for the stack
    char expression[SIZE];     //variable to hold the expression the user inputs
    char again = 'Y';          //to determine if the user wants to input another expression
    int total = 0;             //used to keep track of total when evaluating the expression.
    int digit;                 //variable to store the digit that will be pushed on the stack

    //these variables will be used in determining a digit > 9
    char multDigit[SIZE] = "";
    char digitSwap[SIZE] = "";
    int j = 0;
    int k;

    do
    {
        printf("Please enter the racket expression to be evaluated: \n");
        fgets(expression, SIZE, stdin);

        for(int i = 0; i < strlen(expression); i++)        //builds the linked list for the expression using a for loop
            insertNode(&startPtr, expression[i], &endPtr);

        while(endPtr != NULL)
        {
            if(isspace(endPtr->element))                         //if the last element in the list is a space or new line we move onto the prev node
                endPtr = endPtr->prev;
            else if(endPtr->element == '(' || endPtr->element == ')')    //if the last element is a paren we move to the prev node
                endPtr = endPtr->prev;
            else if(isdigit(endPtr->element) && !(isdigit(endPtr->prev->element))) //if it is a single digit (0-9)
            {   
                digit = endPtr->element - '0';
                endPtr = endPtr->prev;
                push(&stackEnd, digit); //pushes the digit onto the stack
                printStack(&stackEnd);       //when something is pushed onto the stack we want to display the new stack to the user.
            }
            else if(isdigit(endPtr->prev->element))     //if the digit is > 9
            {
                //puts together a char array of the digit >9                
                while(isdigit(endPtr->element))
                {
                    multDigit[j] = endPtr->element;
                    endPtr = endPtr->prev;
                    j++;
                }

                //reverse it so it is in the proper order
                k = 0;

                while(j > 0)
                {
                    digitSwap[k] = multDigit[j-1];  //we need to use another variable digitSwap to store the reversed char array
                    k++;
                    j--;
                }

                digit = atoi(digitSwap); //translates the char array into an int
                push(&stackEnd, digit); //pushes the digit onto the stack
                printStack(&stackEnd);  //when something is pushed onto the stack we want to display the new stack to the user.
            }
            else //the element must be an operator(+, -, /, etc)
            {
                char operator = endPtr->element;

                total = (evaluate((pop(&stackEnd)), operator, (pop(&stackEnd)))); //pop the stack twice to evaluate
                push(&stackEnd, total);    //push the total onto the stack
                printStack(&stackEnd);       //when something is pushed onto the stack we want to display the new stack to the user.
                endPtr = endPtr->prev;
            }
        }

Edit: на случай, если сбивает с толку, как работает мой код.Я использую двусвязный список для прохождения выражения, которое является массивом символов.Я пересекаю его от конца к фронту, например: (+ 3 2)

expression[0]  = '(' 
expression [1] = '+'
expression[2] = ' '

и т. Д. И т. Д.на ')' в этом примере, а затем я использую -> prev для обработки обратных слов.

1 Ответ

0 голосов
/ 24 октября 2018

Это выглядит очень сложно в вашем источнике.Ваш стек должен быть только массивом int с индексом top.И нет необходимости разбивать выражение на множество узлов.У меня под рукой нет компилятора, так что это всего лишь непроверенный пример .

Я думаю, что вам нужно взглянуть на правильный порядок pop () в вызове метода calc ()

int stack[64], stacktop=-1;

void push(int val) {
    stacktop++;
    stack[stacktop] = val;
}
int pop() {
    return (stacktop>=0) ? stack[stacktop--] : 0;
}

int evaluate(char *buf) {
    char *ptr, *mark, *pcpy, *pcpy2, buf2[256];

    for(ptr=buf; *ptr ; ptr++);    // goto end of buf
    for(ptr--; ptr>=buf; ptr--) {
        if(isspace(*ptr)) continue;
        if(*ptr=='(' || *ptr==')') continue;
        for(mark=ptr; ptr>=buf && isdigit(*ptr); ptr--); // test for digits
        if(ptr!=mark) {                                  // found at least 1 digit
            ptr++;
            for(pcpy2=buf2, pcpy=ptr; pcpy<=mark; pcpy++, *pcpy2++)
                *pcpy2=*pcpy;
            *pcpy2='\0';
            push(atoi(buf2));
            continue;
        }
        if(*ptr=='+' || *ptr=='-' || *ptr=='*' || *ptr=='/') {
            push(calculate(pop(), *ptr, pop()));
        }
    }
    return pop();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...