[英]Evaluating an expression using a stack (C)
我需要制作一個堆棧,以與球拍中相同的方式評估表達式。 這是工作輸出的示例:
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的那一點,但它並沒有刪除舊數字,只是返回了它們的值。
這是我的彈出功能:
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;
}
這是我覺得很重要的主要部分。 找到運算符后,將在底部的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;
}
}
編輯:以防混淆我的代碼如何工作。 我正在使用雙向鏈表遍歷作為字符數組的表達式。 我從頭到尾遍歷,例如:(+ 3 2)
expression[0] = '('
expression [1] = '+'
expression[2] = ' '
等,等等。
在此示例中,我使用以')'
開頭的endPtr
遍歷了這些endPtr
,然后使用-> prev
來工作我的backword。
這在您的來源中看起來非常復雜。 您的堆棧只需要是一個具有最高索引的int數組。 無需在多個節點上拆分表達式。 我手邊沒有編譯器,所以這只是一個未經測試的示例 。
我認為您必須在對calculate()的調用中查看pop()的正確順序
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.