C调整动态数组的大小

我正在为C类创建动态数组数据结构。 我已经完成了大部分工作,现在我正在测试它。 它目前在resize时卡住了。 我用过printf来解决这个问题。 看起来resize正在工作,但是当我去添加我的下一个项目后resize时,它就停在那里。

我认为这可能与我的内存分配或我指向的方式有关,并在resize期间释放数组。 我是C的新手,所以这些都是我的观点。

#include  #include  #include "dynArray.h" #include  struct DynArr { TYPE *data; /* pointer to the data array */ int size; /* Number of elements in the array */ int capacity; /* capacity of the array */ }; /* ************************************************************************ Dynamic Array Functions ************************************************************************ */ /* Initialize (including allocation of data array) dynamic array. param: v pointer to the dynamic array param: cap capacity of the dynamic array pre: v is not null post: internal data array can hold cap elements post: v->data is not null */ void initDynArr(DynArr *v, int capacity) { assert(capacity > 0); assert(v!= 0); v->data = (TYPE *) malloc(sizeof(TYPE) * capacity); assert(v->data != 0); v->size = 0; v->capacity = capacity; } /* Allocate and initialize dynamic array. param: cap desired capacity for the dyn array pre: none post: none ret: a non-null pointer to a dynArr of cap capacity and 0 elements in it. */ DynArr* newDynArr(int cap) { assert(cap > 0); DynArr *r = (DynArr *)malloc(sizeof( DynArr)); assert(r != 0); initDynArr(r,cap); return r; } /* Deallocate data array in dynamic array. param: v pointer to the dynamic array pre: none post: d.data points to null post: size and capacity are 0 post: the memory used by v->data is freed */ void freeDynArr(DynArr *v) { if(v->data != 0) { free(v->data); /* free the space on the heap */ v->data = 0; /* make it point to null */ } v->size = 0; v->capacity = 0; } /* Deallocate data array and the dynamic array ure. param: v pointer to the dynamic array pre: none post: the memory used by v->data is freed post: the memory used by d is freed */ void deleteDynArr(DynArr *v) { freeDynArr(v); free(v); } /* Resizes the underlying array to be the size cap param: v pointer to the dynamic array param: cap the new desired capacity pre: v is not null post: v has capacity newCap */ void _dynArrSetCapacity(DynArr *v, int newCap) { DynArr* newArr = newDynArr(newCap); //Create new array with new cap int x; for(x = 0; x data[x]); //copy data } freeDynArr(v); //free old v v->capacity = newCap; v->size = newArr->size; v = newArr; //point v to new array } /* Get the size of the dynamic array param: v pointer to the dynamic array pre: v is not null post: none ret: the size of the dynamic array */ int sizeDynArr(DynArr *v) { return v->size; } /* Adds an element to the end of the dynamic array param: v pointer to the dynamic array param: val the value to add to the end of the dynamic array pre: the dynArry is not null post: size increases by 1 post: if reached capacity, capacity is doubled post: val is in the last utilized position in the array */ void addDynArr(DynArr *v, TYPE val) { /* Check to see if a resize is necessary */ printf("size: %d\tcap: %d\n", v->size, v->capacity); if(v->size >= v->capacity) { printf("in resize.."); _dynArrSetCapacity(v, 2 * v->capacity); } v->data[v->size] = val; //after a resize this doesn't happen. v->size++; } /* Get an element from the dynamic array from a specified position param: v pointer to the dynamic array param: pos integer index to get the element from pre: v is not null pre: v is not empty pre: pos = 0 post: no changes to the dyn Array ret: value stored at index pos */ TYPE getDynArr(DynArr *v, int pos) { /*returns data element at specified position within the array*/ assert(pos = 0); //value is between zero and size return v->data[pos]; //returns deferenced int value at position } /* Remove the element at the specified location from the array, shifts other elements back one to fill the gap param: v pointer to the dynamic array param: idx location of element to remove pre: v is not null pre: v is not empty pre: idx = 0 post: the element at idx is removed post: the elements past idx are moved back one */ void removeAtDynArr(DynArr *v, int idx) { int i; assert(idx = 0); for (i = idx; i size--; } /* ************************************************************************ Stack Interface Functions ************************************************************************ */ /* Returns boolean (encoded in an int) demonstrating whether or not the dynamic array stack has an item on it. param: v pointer to the dynamic array pre: the dynArr is not null post: none ret: 1 if empty, otherwise 0 */ int isEmptyDynArr(DynArr *v) { return (sizeDynArr(v) == 0); } /* Push an element onto the top of the stack param: v pointer to the dynamic array param: val the value to push onto the stack pre: v is not null post: size increases by 1 if reached capacity, capacity is doubled val is on the top of the stack */ void pushDynArr(DynArr *v, TYPE val) { addDynArr(v, val); } /* Returns the element at the top of the stack param: v pointer to the dynamic array pre: v is not null pre: v is not empty post: no changes to the stack */ TYPE topDynArr(DynArr *v) { return getDynArr(v, sizeDynArr(v)-1); } /* Removes the element on top of the stack param: v pointer to the dynamic array pre: v is not null pre: v is not empty post: size is decremented by 1 the top has been removed */ void popDynArr(DynArr *v) { removeAtDynArr(v, sizeDynArr(v)-1); } int main(int argc, char* argv[]){ DynArr* myD = newDynArr(5); int x; addDynArr(myD, 1); addDynArr(myD, 2); //printf("top: %d", sizeDynArr(myD)); //printf("size: %d\ttop: %d\n", sizeDynArr(myD), topDynArr(myD)); for(x = 0; x <= 5; x++){ addDynArr(myD, x); //printf("size: %d\ttop: %d\n", sizeDynArr(myD), topDynArr(myD)); pushDynArr(myD, x * 2); //printf("size: %d\ttop: %d\n", sizeDynArr(myD), topDynArr(myD)); } printf("HI"); deleteDynArr(myD); return 0; } 

您的函数_dynArrSetCapacity不能按预期工作,问题在于以下几行:

  v->capacity = newCap; v->size = newArr->size; v = newArr; //point v to new array } 

最后一条指令基本没用。 v是一个指针。 更改不会影响_dynArrSetCapacity之外的实际使用指针。 因此在addDynArr v->data0 ,你会得到一个分段错误:

  _dynArrSetCapacity(v, 2 * v->capacity); } v->data[v->size] = val; //after a resize this doesn't happen. 

使用v->data = newArr->data或使用指针指针代替。

 v = newArr; //point v to new array 

该行只是将newArr赋给newArr接收的指针的副本 ,它不会修改调用函数中的指针。

要实现这一点,您应该传递指针的地址并让_dynArrSetCapacity接收DynArr**

 void _dynArrSetCapacity(DynArr **v, int newCap) { DynArr* newArr = newDynArr(newCap); //Create new array with new cap int x; for(x = 0; x < sizeDynArr(*v); x++){ addDynArr(newArr, (*v)->data[x]); //copy data } freeDynArr(*v); //free old v // v->capacity = newCap; These are superfluous, since we change the pointer itself // v->size = newArr->size; *v = newArr; //point v to new array } 

但更好的解决方案是只重新分配数组,

 void _dynArrSetCapacity(DynArr *v, int newCap) { TYPE *temp = realloc(v->data,newCap * sizeof *temp); if (!temp) { // alloc failure exit(EXIT_FAILURE); } v->data = temp; v->capacity = newCap; v->size = newArr->size; }