簡體   English   中英

在結構內重新分配數組

[英]Reallocating array within a struct

我正在為學校編寫一個程序,要求我們創建一個結構,該結構具有一個整數數組以及兩個整數變量(容量和大小),您可以猜出它的大小和容量。 當我需要為數組重新分配空間時,麻煩就開始了(教授不希望我們使用realloc )。 這是代碼...

dynamicArray.h文件

#ifndef DYNAMIC_ARRAY_INCLUDED
#define DYNAMIC_ARRAY_INCLUDED 1

#ifndef __TYPE
#define __TYPE
# define TYPE int
# endif

typedef struct DynArr DynArr;

/* Dynamic Array Functions */
void initDynArr(DynArr *v, int capacity);
DynArr *newDynArr(int cap);

void freeDynArr(DynArr *v);
void deleteDynArr(DynArr *v);

int sizeDynArr(DynArr *v);

void addDynArr(DynArr *v, TYPE val);    

#endif

dynamicArray.c文件

#include <assert.h>
#include <stdlib.h>
#include "dynArray.h"

struct DynArr
{
    TYPE *data;     /* pointer to the data array */
    int size;       /* Number of elements in the array */
    int capacity;   /* capacity ofthe array */
};

void printArray(DynArr *v)
{
    for (int i = 0; i < v->size; i++)
    {
        printf("%d, ", v->data[i]);

    }
    printf("\n");
}

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    /*check that v is initialized*/
    assert(v!=0);

    /*create temporary array with new capacity*/
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; i++)
    {
        tmp->data[i] = v->data[i];
        tmp->size++;
    }

    /*delete contents of old array*/
    deleteDynArr(v);

    /*assign address of new array to v*/
    v = tmp;
}

void deleteDynArr(DynArr *v)
{
    freeDynArr(v);
    free(v);
}

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;
}

DynArr *newDynArr(int cap)
{
    assert(cap > 0);
    DynArr *r = (DynArr *)malloc(sizeof( DynArr));
    assert(r != 0);
    initDynArr(r,cap);
    return r;
}

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;
}

main.c文件

#include <stdio.h>
#include <stdlib.h>
#include "dynArray.h"

#define TYPE int

int main(int argc, char* argv[]){

    DynArr *dyn;
    dyn = newDynArr(2);

    printf("\n\nTesting addDynArr...\n");
    addDynArr(dyn, 3);
    printArray(dyn);
    addDynArr(dyn, 4);
    printArray(dyn);
    addDynArr(dyn, 10);
    printArray(dyn);
    addDynArr(dyn, 5);
    printArray(dyn);
    addDynArr(dyn, 6);
    printArray(dyn);

    return 0;
}

我削減了代碼(我知道是否可能看起來不太像),所以這是我問題的要點。 我在dynamicArray.c文件中遇到分段錯誤。 具體在此功能

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

在v-> data [v-> size] = val處; 線。 我確實注意到,當我在前面提到的代碼行之前檢查v-> size的值是否正確時,它給了我垃圾值。 這使我認為,當我將v傳遞給_dynArrSetCapacity函數時,它是通過值而不是通過引用傳遞的,但是我不知道如何實現。 任何幫助將不勝感激。

問題出在void _dynArrSetCapacity(DynArr *v, int newCap) 您可能需要檢查所有與內存重新分配有關的功能,以解決類似問題。

從技術上講,C中沒有引用,因此每個參數都按值傳遞或復制。 但是復制的是指針,而不是整個DynArray對象。 這意味着當您執行deleteDynArray() ,內存會像您期望的那樣消失,但是當您到達v = tmp; ,它將更改本地v (本地副本)的值,而不是傳入的v的值v->data[v->size] = val; ,您可能正在訪問尚未分配的內存,從而導致該錯誤。

最快的解決方案(IMO並不是最好的解決方案)是對執行取消分配的任何函數使用雙指針而不是單指針,如下所示:

void _dynArrSetCapacity(DynArr **v, int newCap)
{
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    ......
    /*delete contents of old array*/
    deleteDynArr(*v);

    /*assign address of new array to v*/
    *v = tmp;
    (*v)->size = newCap;
}

還有一種選擇,我認為可能會更好。 您不必重新分配整個對象。 DynArray對象中僅包含所有相關對象的內存塊: TYPE *data

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    TYPE *tmp = (TYPE*)malloc(sizeof(Type) * newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; ++i)
        tmp[i] = v->data[i];
    /*delete contents of old array*/
    free(v->data);

    /*assign address of new array to v*/
    v->data = tmp;
    v->size = newCap;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM