2013-09-25 51 views
3

我在一個操作系統類,我必須編寫一個簡單的堆棧程序(主函數只是確定用戶要求你做什麼)。如果不需要C語言,我會在很久以前完成這個工作,但是因爲我不擅長編寫C代碼,它有一個「錯誤」......迄今爲止的錯誤是,它只是繼續「流行「相同的價值。 (它實際上並沒有彈出任何東西)。我認爲這是因爲我不明白結構和指針是如何工作的。或者這是一個不太明顯的編碼錯誤?簡單的堆棧程序C

#include <stdio.h> 

struct node { 
    int data; 
    struct node *next; 
    struct node *prev; 
} first; 

void push(int); 
void pop(); 

int main(void) 
{ 
    int command = 0; 

    while (command != 3) 
    { 
     printf("Enter your choice:\n1) Push integer\n2) Pop Integer\n3) Quit.\n"); 
     scanf("%d",&command); 
     if (command == 1) 
     { 
      // push 
      int num; 
      scanf("%d",&num); 
      push(num); 
     } 
     else 
     { 
      if (command == 2) 
      { 
       pop(); 
      } 
      else 
      { 
       if (command != 3) 
       { 
        printf("Command not understood.\n"); 
       } 
      } 
     } 
    } 

    return 0; 
} 

void push (int x) 
{ 
    struct node newNode; 
    newNode.data = x; 
    newNode.prev = NULL; 
    newNode.next = &first; 
    first = newNode; 
    printf("%d was pushed onto the stack.\n", first.data); 
} 

void pop() 
{ 
    if (first.data == '\0') 
    { 
     printf("Error: Stack Empty.\n"); 
     return; 
    } 
    printf("%d was popped off the stack.\n", first.data); 
    first = *(first.next); 
    first.prev = NULL; 
} 

回答

2

什麼是&first的價值?提示,它始終是相同的,因爲first是靜態分配的。即使你改變結構的內容,地址也不會改變。這可能會告訴你爲什麼push中有一個錯誤。如果您打算使用不同尺寸的結構,則需要使用mallocfree

3

的問題是,first是一個單一的全球node,並且它是唯一node你曾經有(除臨時本地node您的來電push內)。

這條線:

first = newNode; 

只是複製的newNode內容在進入first;並且由於newNode.next指向first,這意味着現在first.next指向first,所以您有一個單元素循環鏈表。

同樣,這條線:的*(first.next)超過成first

first = *(first.next); 

只是複製內容;因爲(由於上述原因)*(first.next)first

要解決此問題,實際上需要使用malloc(和free)動態創建節點。並且您的全局變量應該是指針— a node * —,它總是指向堆棧的頂層元素。 (更好的是,您的pushpop函數應該將first作爲參數,而不是將其作爲全局變量。不需要這些函數只允許單個堆棧存在。)

1

當您必須管理記住你自己,正如C要求你做的那樣,你需要知道被稱爲棧和堆的內存區域之間的區別。 (此「堆棧」與您在程序中創建的數據結構略有不同。)

您的push()函數正在堆棧上創建新節點;當函數退出堆棧時,彈出新節點佔用的內存。你看到你輸入的值是因爲你的程序非常簡單。如果它調用其他函數做其他事情,他們幾乎肯定會覆蓋堆棧的那部分,並且當您調用pop()時,您會看到垃圾。

正如其他人所指出的,您需要使用函數malloc()free(),這些函數爲您提供堆而不是堆棧的內存。

1

如果要使用鏈接列表進行堆棧,請將first作爲指針變量。那麼當你將一個新節點推入堆棧時,通過malloc()在堆內存上分配一個新節點。我知道你打算用它來指向棧頂。對?

在您的代碼中,first變量被新節點覆蓋,因爲它不是指針變量而是值變量。這導致結果丟失了堆棧的頂層節點。

5

首先應該是一個指針。將其更改爲struct node * first;

主要初始化first = NULL;

改變你推/彈出操作如下,

void push (int x) 
{ 
    struct node *newNode;// It should be a pointer 
newNode = (struct node *)malloc(sizeof(struct node)); 
    newNode->data = x; 
    //newNode.prev = NULL; // You don't need this 
    newNode->next = first; 
    first = newNode; 
    printf("%d was pushed onto the stack.\n", first->data); 
} 

void pop() 
{ 
struct node *prevPtr; 
    //if (first.data == '\0') 
    if (first == NULL) // check if stack is empty 
    { 
     printf("Error: Stack Empty.\n"); 
     return; 
    } 

    printf("%d was popped off the stack.\n", first->data); 
prevPtr = first; 
    first = first->next; 

free(prevPtr); 
} 
1
void pop() 
{ 
struct node *prevPtr; 
//if (first.data == '\0') 
if (first == NULL) 
{ 
    printf("Error: Stack Empty.\n"); 
    return; 
} 

printf("%d was popped off the stack.\n", first->data); 
prevPtr = first; 
first = first->next; 

free(prevPtr); 
}