programing

동적 크기의 구조체 어레이를 작성하려면 어떻게 해야 합니까?

prostudy 2022. 7. 5. 22:04
반응형

동적 크기의 구조체 어레이를 작성하려면 어떻게 해야 합니까?

미리 정의된 크기의 구조체 배열을 작성하는 방법을 알고 있습니다.그러나 어레이를 확장할 수 있도록 동적 구조 어레이를 작성하는 방법은 있습니까?

예를 들어 다음과 같습니다.

    typedef struct
    {
        char *str;
    } words;

    main()
    {
        words x[100]; // I do not want to use this, I want to dynamic increase the size of the array as data comes in.
    }

이게 가능합니까?


바로는 다음과 같습니다.words* array = (words*)malloc(sizeof(words) * 100);

100을 삭제하고 데이터가 들어오는 대로 저장하려고 합니다.따라서 76개의 데이터가 들어오면 100개가 아닌 76개의 데이터를 저장하고 싶습니다.프로그램에 얼마나 많은 데이터가 들어오고 있는지 모르는 것 같습니다.위에서 정의한 구조에서는 다음과 같이 첫 번째 "인덱스"를 작성할 수 있습니다.

    words* array = (words*)malloc(sizeof(words));

다만, 그 후에 동적으로 요소를 어레이에 추가하고 싶다.제가 문제 영역을 충분히 명확하게 설명했길 바랍니다.주요 과제는 두 번째 필드를 동적으로 추가하는 것입니다. 적어도 현시점에서는 이것이 과제입니다.


하지만 약간의 진전이 있었습니다.

    typedef struct {
        char *str;
    } words;

    // Allocate first string.
    words x = (words) malloc(sizeof(words));
    x[0].str = "john";

    // Allocate second string.
    x=(words*) realloc(x, sizeof(words));
    x[1].FirstName = "bob";

    // printf second string.
    printf("%s", x[1].str); --> This is working, it's printing out bob.

    free(x); // Free up memory.

    printf("%s", x[1].str); --> Not working since its still printing out BOB even though I freed up memory. What is wrong?

제가 몇 가지 오류를 확인했는데, 이것이 제가 발견한 것입니다.x용 메모리를 비운 후 다음을 추가합니다.

    x=NULL;

x를 인쇄하려고 하면 원하는 에러가 납니다.그럼 적어도 제 컴파일러에서는 프리 기능이 작동하지 않는 건가요?DevC를 사용한다고?


감사합니다. 이제 이해했습니다.

FirstName은 malloc에 의해 할당되지 않은 char 배열에 대한 포인터이며, 포인터만 할당되며, 무료 호출 후 메모리는 삭제되지 않고 나중에 덮어쓰기되도록 힙에서 사용 가능한 것으로 표시됩니다.– Matt Smith

갱신하다

나는 내 구조들의 배열을 모듈화해서 함수에 넣으려고 했지만, 아무 것도 작동하지 않는 것 같다.아주 간단한 걸 하려고 하는데 어떻게 해야 할지 모르겠어요.이전과 같은 라인입니다.데이터를 로드하는 다른 기능인 로드 데이터일 뿐이며 인쇄를 해야 합니다.어떻게 하면 될까요?제 코드는 다음과 같습니다.

    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
    # include <ctype.h>

    typedef struct
    {
        char *str1;
        char *str2;
    } words;

    void LoadData(words *, int *);

    main()
    {
        words *x;
        int num;

        LoadData(&x, &num);

        printf("%s %s", x[0].str1, x[0].str2);
        printf("%s %s", x[1].str1, x[1].str2);

        getch();
    }//

    void LoadData(words *x, int * num)
    {
        x = (words*) malloc(sizeof(words));

        x[0].str1 = "johnnie\0";
        x[0].str2 = "krapson\0";

        x = (words*) realloc(x, sizeof(words)*2);
        x[1].str1 = "bob\0";
        x[1].str2 = "marley\0";

        *num=*num+1;
    }//

이 간단한 테스트 코드가 깨지고 있는데 왜 그랬는지 모르겠어요.어디에 버그가 있습니까?

C뿐만 아니라 C++로 태그가 붙여져 있습니다.

C++를 사용하면 훨씬 쉬워집니다.표준 템플릿 라이브러리에는 벡터라는 템플릿이 있으며, 이를 통해 개체 목록을 동적으로 작성할 수 있습니다.

#include <stdio.h>
#include <vector>

typedef std::vector<char*> words;

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

        words myWords;

        myWords.push_back("Hello");
        myWords.push_back("World");

        words::iterator iter;
        for (iter = myWords.begin(); iter != myWords.end(); ++iter) {
                printf("%s ", *iter);
        }

        return 0;
}

C를 사용하는 것이 훨씬 어렵다면 yes malloc, realloc, free가 도움이 됩니다.대신 링크 목록 데이터 구조를 사용하는 것이 좋습니다.일반적으로 확장이 용이하지만 랜덤 액세스가 용이하지는 않습니다.

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

typedef struct s_words {
        char* str;
        struct s_words* next;
} words;

words* create_words(char* word) {
        words* newWords = malloc(sizeof(words));
        if (NULL != newWords){
                newWords->str = word;
                newWords->next = NULL;
        }
        return newWords;
}

void delete_words(words* oldWords) {
        if (NULL != oldWords->next) {
                delete_words(oldWords->next);
        }
        free(oldWords);
}

words* add_word(words* wordList, char* word) {
        words* newWords = create_words(word);
        if (NULL != newWords) {
                newWords->next = wordList;
        }
        return newWords;
}

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

        words* myWords = create_words("Hello");
        myWords = add_word(myWords, "World");

        words* iter;
        for (iter = myWords; NULL != iter; iter = iter->next) {
                printf("%s ", iter->str);
        }
        delete_words(myWords);
        return 0;
}

이런, 세상에서 가장 긴 답변이라 미안해요.따라서 "링크 목록 코멘트를 사용하지 않음"에 대한 WRT:

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

typedef struct {
    char** words;
    size_t nWords;
    size_t size;
    size_t block_size;
} word_list;

word_list* create_word_list(size_t block_size) {
    word_list* pWordList = malloc(sizeof(word_list));
    if (NULL != pWordList) {
        pWordList->nWords = 0;
        pWordList->size = block_size;
        pWordList->block_size = block_size;
        pWordList->words = malloc(sizeof(char*)*block_size);
        if (NULL == pWordList->words) {
            free(pWordList);
            return NULL;    
        }
    }
    return pWordList;
}

void delete_word_list(word_list* pWordList) {
    free(pWordList->words);
    free(pWordList);
}

int add_word_to_word_list(word_list* pWordList, char* word) {
    size_t nWords = pWordList->nWords;
    if (nWords >= pWordList->size) {
        size_t newSize = pWordList->size + pWordList->block_size;
        void* newWords = realloc(pWordList->words, sizeof(char*)*newSize); 
        if (NULL == newWords) {
            return 0;
        } else {    
            pWordList->size = newSize;
            pWordList->words = (char**)newWords;
        }

    }

    pWordList->words[nWords] = word;
    ++pWordList->nWords;


    return 1;
}

char** word_list_start(word_list* pWordList) {
        return pWordList->words;
}

char** word_list_end(word_list* pWordList) {
        return &pWordList->words[pWordList->nWords];
}

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

        word_list* myWords = create_word_list(2);
        add_word_to_word_list(myWords, "Hello");
        add_word_to_word_list(myWords, "World");
        add_word_to_word_list(myWords, "Goodbye");

        char** iter;
        for (iter = word_list_start(myWords); iter != word_list_end(myWords); ++iter) {
                printf("%s ", *iter);
        }

        delete_word_list(myWords);

        return 0;
}

어레이를 동적으로 할당하려면stdlib.h.

하여 100 words 해서 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조, 구조.

words* array = (words*)malloc(sizeof(words) * 100);

는, 「메모리 사이즈」에 .malloc.void )void*이 포인터 타입은 '포인터 타입')으로 하고 포인터 타입이 될 수 이 경우는 다음과 같습니다.words*.

sizeof하면, 「이러다」의를 알 수 있습니다.words그 사이즈에 할당할 요소의 수를 곱합니다.

꼭 하세요.free()메모리 누수를 방지하기 위해 사용한 힙메모리를 해방합니다.

free(array);

배열의 " "를 사용해 .realloc처럼, 만약 것을 , 당신은 많은 것을 할 수 있다는 하세요.realloc메모리가 fragment화될 수 있습니다.프로그램에 필요한 메모리 용량을 줄이기 위해 어레이 크기를 동적으로 조정하려면 너무 많은 작업을 수행하지 않는 것이 좋습니다.reallocs.

이것은 C++를 사용할 수 없기 때문에 아쉽게도 더 어려워지는 학술적인 운동인 것 같습니다.기본적으로 할당에 대한 오버헤드의 일부를 관리하고 나중에 크기를 조정해야 할 경우 할당된 메모리 양을 추적해야 합니다.여기서 C++ 표준 라이브러리가 빛을 발합니다.

예를 들어, 다음 코드는 메모리를 할당하고 나중에 크기를 조정합니다.

// initial size
int count = 100;
words *testWords = (words*) malloc(count * sizeof(words));
// resize the array
count = 76;
testWords = (words*) realloc(testWords, count* sizeof(words));

이 예에서는 포인터를 문자에 할당하고 있을 뿐이지만 문자열 자체를 할당해야 합니다.또한 가장 중요한 것은 마지막에 포인터를 해방하는 것입니다.따라서 이 코드는 char에 100개의 포인터를 할당한 후 76으로 크기를 조정합니다.단, 문자열 자체는 할당하지 않습니다.

당신은 실제로 위와 같은 문자열에 글자 수를 할당하고 싶지만 단어를 char로 바꾸고 싶은 것 같습니다.

편집: 또, 공통의 태스크를 실행하는 기능을 작성해, 일관성을 강화하는 것은 매우 의미가 있기 때문에, 코드를 카피할 필요가 없습니다.예를 들어 a) 구조물을 할당하고 b) 구조물에 값을 할당하고 c) 구조물을 개방하도록 할 수 있습니다.다음과 같은 경우가 있습니다.

// Allocate a words struct
words* CreateWords(int size);
// Assign a value
void AssignWord(word* dest, char* str);
// Clear a words structs (and possibly internal storage)
void FreeWords(words* w);

EDIT: 구조 크기 변경에 관한 한 char 배열 크기 변경과 동일합니다.단, Structure Array를 크게 하면 새로운 어레이 항목을 NULL로 초기화해야 합니다.또한 Structure Array를 작게 하면 Structure Array 크기를 조정하기 전에 이미 할당된 빈 항목(및 할당된 항목만)을 삭제하기 전에 정리해야 합니다.이것이 내가 이것을 관리하기 위해 도우미 기능을 만들 것을 제안한 주된 이유입니다.

// Resize words (must know original and new size if shrinking
// if you need to free internal storage first)
void ResizeWords(words* w, size_t oldsize, size_t newsize);

다른 옵션은 링크된 목록입니다.프로그램이 데이터 구조를 어떻게 사용하는지 분석해야 합니다. 랜덤 액세스가 필요하지 않은 경우 재할당보다 더 빠를 수 있습니다.

C++에서 벡터를 사용합니다.어레이와 비슷하지만 요소를 쉽게 추가하거나 제거할 수 있으며 메모리 할당 및 할당 해제를 처리합니다.

질문 제목에 C라고 써있는 건 알지만, 당신은 당신의 질문에 C와 C++로 태그를 붙였습니다.

이전 업데이트의 코드는 컴파일되지 않습니다.실행은 말할 것도 없습니다.&x를 Load Data에 전달합니다.&x는 **words 타입을 가지고 있지만 LoadData는 words*를 예상합니다.물론 스택을 가리키는 포인터로 재할당을 호출하면 크래시 됩니다.

이를 수정하는 방법은 LoadData를 변경하여 단어를 받아들이는 것입니다**. 이 경우 포인터를 실제로 main()에서 수정할 수 있습니다.예를 들어 재할당 콜은 다음과 같습니다.

*x = (words*) realloc(*x, sizeof(words)*2);

이는 int가 아닌 int*가 되는 것과 같은 원칙입니다.

이것 외에도, 당신은 단어의 문자열이 어떻게 저장되었는지 알아내야 합니다.str2 = "marley\0"과 같이 const 문자열을 char *에 할당하는 것은 허용되지만, C에서도 올바른 솔루션은 거의 없습니다.

또 다른 포인트는 문자열 끝에 0이 두 개 필요하지 않는 한 "marley\0"을 사용할 필요가 없다는 것입니다.컴파일러는 모든 문자열 리터럴 끝에 0을 추가합니다.

테스트 코드의 경우: 함수의 포인터를 수정하려면 "포인터 투 포인터"를 함수에 전달해야 합니다.수정된 코드는 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct
{
    char *str1;
    char *str2;
} words;

void LoadData(words**, int*);

main()
{
    words **x;
    int num;

    LoadData(x, &num);

    printf("%s %s\n", (*x[0]).str1, (*x[0]).str2);
    printf("%s %s\n", (*x[1]).str1, (*x[1]).str2);
}

void LoadData(words **x, int *num)
{
    *x = (words*) malloc(sizeof(words));

    (*x[0]).str1 = "johnnie\0";
    (*x[0]).str2 = "krapson\0";

    *x = (words*) realloc(*x, sizeof(words) * 2);
    (*x[1]).str1 = "bob\0";
    (*x[1]).str2 = "marley\0";

    *num = *num + 1;
}

모든 코더는 코드를 쉽게 이해할 수 있도록 단순화할 필요가 있습니다.초보자도 마찬가지입니다.

개념을 이해하면 동적으로 사용하는 구조 배열은 쉽습니다.

// Dynamically sized array of structures

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

struct book 
{
    char name[20];
    int p;
};              //Declaring book structure

int main () 
{
    int n, i;      

    struct book *b;     // Initializing pointer to a structure
    scanf ("%d\n", &n);

    b = (struct book *) calloc (n, sizeof (struct book));   //Creating memory for array of structures dynamically

    for (i = 0; i < n; i++)
    {
        scanf ("%s %d\n", (b + i)->name, &(b + i)->p);  //Getting values for array of structures (no error check)
    }          

    for (i = 0; i < n; i++)
    {
        printf ("%s %d\t", (b + i)->name, (b + i)->p);  //Printing values in array of structures
    }

    scanf ("%d\n", &n);     //Get array size to re-allocate    
    b = (struct book *) realloc (b, n * sizeof (struct book));  //change the size of an array using realloc function
    printf ("\n");

    for (i = 0; i < n; i++)
    {
        printf ("%s %d\t", (b + i)->name, (b + i)->p);  //Printing values in array of structures
    }

    return 0;
}   

어레이를 동적으로 확장할 경우 malloc()를 사용하여 일정량의 메모리를 동적으로 할당한 후 부족할 때마다 realoc()를 사용해야 합니다.일반적인 방법은 지수 증가 함수를 사용하여 적은 양의 고정된 양을 할당한 다음 할당된 양을 복제하여 어레이를 증가시키는 것입니다.

코드 예는 다음과 같습니다.

size = 64; i = 0;
x = malloc(sizeof(words)*size); /* enough space for 64 words */
while (read_words()) {
    if (++i > size) {
        size *= 2;
        x = realloc(sizeof(words) * size);
    }
}
/* done with x */
free(x);

C++에서의 방법은 다음과 같습니다.

size_t size = 500;
char* dynamicAllocatedString = new char[ size ];

모든 구조체 또는 c++ 클래스에 동일한 주체를 사용합니다.

언급URL : https://stackoverflow.com/questions/260915/how-can-i-create-a-dynamically-sized-array-of-structs

반응형