2013-11-25 81 views
0

所以我在使用我的pop()函數時遇到了一個問題,當我第一次調用pop()函數時,它返回的項目沒有問題,但是當它嘗試連續彈出第二個項目,則失敗。我似乎無法弄清楚爲什麼,在我的功能中是否有某些我想念的東西?PHP pop()函數的問題

#define DEFAULT_CAPACITY 16 

struct stack { 
    size_t capacity; 
    size_t size; 
    stack_item *data; 
}; 

stack *new_stack (void) { 
    stack *this = malloc (sizeof (stack)); 
    assert (this != NULL); 
    this->capacity = DEFAULT_CAPACITY; 
    this->size = 0; 
    this->data = calloc (this->capacity, sizeof (stack_item)); 
    assert (this->data != NULL); 
    return this; 
} 

void free_stack (stack *this) { 
    assert (empty_stack (this)); 
    free (this->data); 
    free (this); 
} 

static bool full_stack (stack *this) { 
    return this->size == this->capacity; 
} 

static void realloc_stack (stack *this) { 
    size_t old_capacity = this->capacity; 
    this->capacity *= 2; 
    this->data = realloc (this->data, this->capacity); 
    memset (this->data + old_capacity, 0, old_capacity); 
    assert (this->data != NULL); 
} 


void push_stack (stack *this, stack_item item) { 
    if (full_stack (this)) realloc_stack (this); 
    //increase size of stack 
    this->data[this->size] = item; 
    this->size++; 
} 

stack_item pop_stack (stack *this) { 
    assert (! empty_stack (this)); 
    printf("Stack size: %lu\n", this->size); 
    return this->data[this->size--]; 
} 
+0

它是如何失敗?你可以添加輸出嗎?什麼是'stack_item'? –

+0

你應該檢查大小的範圍。提供更多的代碼。 – moeCake

+0

您可能會在斷言失敗,這意味着您的empty_stack函數可能有錯誤(返回false)。另一件需要考慮的是,您的stack_item *數據可能無法正確構建。發佈錯誤以及如何填充和檢查堆棧。 –

回答

2

取決於你的意思是「失敗」。

有許多原因,它可能會失敗,如(絕非詳盡):推送數據

  • 代碼不正確。
  • 您尚未創建足夠大的容量。
  • 你還沒有推足夠的物品彈出(堆棧下溢)。

第一件事你應該做的是爲調試創建dump_stack功能,沿着線:

void dump_stack (char *desc, stack *this) { 
    printf ("%s: size/capacity: %lu/%lu\n", 
     desc, this->size, this->capacity); 
    for (size_t idx = 0; idx < this->size; idx++) { 
     // print out this->data[idx], depends on data type 
    } 
} 

這將在搞清楚大大有助於您的問題在於,如果你把它每次堆棧操作後(push,pop,peek,clear,dup,rot,2dup,3rot等)。


既然您已經添加了一些代碼,那麼您需要查看一些內容。

首先,你的stack_item類型。除非這與char的尺寸完全相同,否則您的內存分配功能不正確。例如,如果它是一個四字節整數,則需要分配四倍的內存。這可以通過將分配乘以sizeof(stack_item)來解決。

您已經完成了初始calloc調用(因爲您必須爲此提供一個大小),但不是在隨後的realloc調用中。


其次,在你的realloc_stack功能,你真的應該assertmemset之前。如果由於某種原因重新分配失敗,那麼對內存執行任何都不是個好主意。


三是依託assert趕上,可能會或可能不會在運行時出現的錯誤是一個壞主意。這是因爲assert通常在非調試代碼中沒有任何作用(基於NDEBUG),因此,如果內存不足,則無法解決問題。您可能需要與exit()(例如)一起提供您自己的錯誤處理內容。

我也不是一個真正的庫類型代碼的大風扇,如果它有問題,從下面拉出地毯 - 我總是喜歡讓它返回給調用者一個指示,並讓決定什麼(這就是爲什麼我永遠不會在生產代碼中使用GMP,因爲它在內存用完時完全可以)。


四,使用callocmemset這裏幾乎可以肯定是一種浪費,因爲你的代碼知道哪裏堆端是基於size。是否那些高於size但低於capacity的條目設置爲0或者某些任意值是無關緊要的,因爲如果沒有先設置它們(通過按下操作),您將永遠不會使用它們。

+2

相當不錯的泛化爲AI機器人:) –

+0

感謝您的幫助和指導,非常感謝。 – marcello