2013-11-25 52 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