문제

배열을 인수로 사용하여 배열에 값을 추가하고(필요한 경우 크기를 늘림) 항목 수를 반환하는 함수를 만들려고 합니다.지금까지 나는 다음을 가지고 있습니다 :

int main(int argc, char** argv) {
    int mSize = 10;
    ent a[mSize];
    int n;
    n = addValues(a,mSize);

    for(i=0;i<n;i++) {
       //Print values from a
    }
}

int addValues(ent *a, int mSize) {
    int size = mSize;

    i = 0;

    while(....) { //Loop to add items to array
        if(i>=size-1) { 
            size = size*2;
            a = realloc(a, (size)*sizeof(ent));
        }
        //Add to array
        i++;
    }
    return i;
}

이는 mSize가 배열의 모든 잠재적 요소를 수용할 만큼 충분히 큰 경우 작동하지만 크기 조정이 필요한 경우 분할 오류가 발생합니다.

나는 또한 다음을 시도했습니다.

int main(int argc, char** argv) {
    ...
    ent *a;
    ...
}

int addValues(ent *a, int mSize) {
    ...
    a = calloc(1, sizeof(ent);
    //usual loop
    ...
}

소용이 없습니다.

나는 이것이 realloc를 호출할 때 'a'의 복사본이 다른 곳을 가리키기 때문이라고 가정합니다. 'a'가 항상 같은 위치를 가리키도록 이것을 수정하는 것이 어떻게 가능합니까?

나는 이것을 올바르게 진행하고 있습니까?C에서 동적 구조를 처리하는 더 좋은 방법이 있습니까?이를 처리하기 위해 연결 목록을 구현해야 합니까?

도움이 되었습니까?

해결책

여기서 주요 문제는 스택 알 로케이션 배열과 함께 Realloc을 사용하려고한다는 것입니다. 당신은 :

ent a[mSize];

스택에 자동 할당됩니다. 나중에 realloc ()를 사용하려면 다음과 같이 malloc ()을 사용하여 힙에 배열을 만듭니다.

ent *a = (ent*)malloc(mSize * sizeof(ent));

Malloc 라이브러리 (및 realloc () 등이 배열에 대해 알고 있습니다. 이것의 모습에서 당신은 혼란 스러울 수 있습니다 C99 가변 길이 배열 진실로 동적 배열,이 문제를 해결하기 전에 차이점을 이해하십시오.

그러나 실제로 C로 동적 배열을 작성하는 경우 OOP-ish 디자인을 사용하여 배열에 대한 정보를 캡슐화하고 사용자로부터 숨겨야합니다. 배열에 대한 정보 (예 : 포인터 및 크기)를 구조 및 작업 (예 : 할당, 요소 추가, 요소 제거, 자유 등)을 구조물과 함께 작동하는 특수 기능으로 통합하려고합니다. 그래서 당신은 다음과 같습니다.

typedef struct dynarray {
   elt *data;
   int size;
} dynarray;

그리고 Dynarrays와 함께 작동하는 일부 기능을 정의 할 수 있습니다.

// malloc a dynarray and its data and returns a pointer to the dynarray    
dynarray *dynarray_create();     

// add an element to dynarray and adjust its size if necessary
void dynarray_add_elt(dynarray *arr, elt value);

// return a particular element in the dynarray
elt dynarray_get_elt(dynarray *arr, int index);

// free the dynarray and its data.
void dynarray_free(dynarray *arr);

이런 식으로 사용자는 물건을 할당하는 방법이나 배열의 크기를 정확히 기억할 필요가 없습니다. 당신을 시작하게되기를 바랍니다.

다른 팁

배열에 대한 포인터에 대한 포인터가 전달되도록 재 작업을 시도하십시오. ent **a. 그런 다음 배열의 새 위치에서 발신자를 업데이트 할 수 있습니다.

이것이 OOP를 사용하는 좋은 이유입니다. 예, C에서 OOP를 수행 할 수 있으며 올바르게 수행하면 멋지게 보입니다.

이 간단한 경우 상속이나 다형성이 필요하지 않으며 캡슐화 및 방법 개념만이 필요합니다.

  • 길이와 데이터 포인터가있는 구조를 정의하십시오. 아마도 요소 크기 일 수도 있습니다.
  • 해당 구조물에 대한 포인터에서 작동하는 Getter/Setter 기능을 작성하십시오.
  • 'Grow'기능은 구조물 내에서 데이터 포인터를 수정하지만 모든 구조물 포인터는 유효합니다.

Main의 변수 선언을 변경 한 경우

ent *a = NULL;

이 코드는 스택 알 로케이션 배열을 제거하지 않음으로써 상상했던 것처럼 더 잘 작동합니다. realloc이 마치 사용자가 Malloc (size)라고하는 것처럼 취급하기 때문에 A에서 NULL을 설정합니다. 이 변경으로 AddValue의 프로토 타입을 변경해야합니다.

int addValues(ent **a, int mSize)

그리고 코드는 Realloc 실패의 경우를 처리해야합니다. 예를 들어

while(....) { //Loop to add items to array
    tmp = realloc(*a, size*sizeof(ent));
    if (tmp) {
        *a = tmp;
    } else {
        // allocation failed. either free *a or keep *a and
        // return an error
    }
    //Add to array
    i++;
}

현재 버퍼가 원래 코드를 만드는 크기 조정이 필요한 경우 대부분의 REALLOC 구현이 내부적으로 두 배나 많은 메모리를 할당 할 것으로 예상합니다.

size = size * 2;

불필요한.

배열 포인터를 값으로 전달하고 있습니다. 이것이 의미하는 바는 다음과 같습니다.

int main(int argc, char** argv) {
    ...
    ent *a; // This...
    ...
}

int addValues(ent *a, int mSize) {
    ...
    a = calloc(1, sizeof(ent); // ...is not the same as this
    //usual loop
    ...
}

그래서 a의 값을 바꾸십시오 addValues 함수는 메인에서 A의 값을 변경하지 않습니다. 메인에서 A의 값을 변경하려면 참조를 전달해야합니다. addValues. 현재 A의 가치가 복사되어 전달됩니다. addValues. 사용에 대한 참조를 전달하려면 :

int addValues (int **a, int mSize)

그리고 그것을 다음과 같다고 부릅니다.

int main(int argc, char** argv) {
    ...
    ent *a; // This...
    ...
    addValues (&a, mSize);
}

에서 addValues, 다음과 같은 요소에 액세스하십시오.

(*a)[element]

그리고 다음과 같이 배열을 재 할당하십시오.

(*a) = calloc (...);

Xahtep은 호출자가 realloc()이 배열을 새 위치로 이동할 수 있다는 사실을 처리할 수 있는 방법을 설명합니다.이렇게 하는 한 괜찮을 것입니다.

큰 배열로 작업을 시작하면 realloc()이 비용이 많이 들 수 있습니다.이제 다른 데이터 구조(연결된 목록, 이진 트리 등)를 사용할 생각을 시작할 때입니다.

언급했듯이 포인터를 포인터로 전달하여 포인터 값을 업데이트해야합니다.
그러나 나는 재 설계를 제안 하고이 기술을 피할 수 있습니다. 대부분의 경우 피할 수 있고 피해야합니다. 당신이 정확히 무엇을 달성하려고 노력하는지 알지 못하면 대체 디자인을 제안하기는 어렵지만 99%는 다른 방식으로 가능하다고 확신합니다. 그리고 AS 하비에르 슬픈 - 객체 지향을 생각하면 항상 더 나은 코드를 얻게됩니다.

C를 사용해야합니까? 이것은 C ++의 "std :: vector"를 잘 적용하는 것입니다. 이것은 정확하게 동적으로 크기가 큰 배열입니다 (글을 쓰고 디버깅 할 필요가없는 단일 통화로 쉽게 크기를 조정합니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top