c - 如何创建动态大小的结构数组?

标签 c dynamic memory-management

我知道如何创建具有预定义大小的结构数组。但是,有没有一种方法可以创建一个动态的结构数组,使该数组变得更大?

例如:

    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 个数据字段,我想存储 76 个而不是 100 个。我假设我不知道有多少数据正在进入我的程序。在我上面定义的结构中,我可以将第一个“索引”创建为:

    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,我会得到一个错误,这正是我想要的。那么是不是 free 函数不起作用,至少在我的编译器上是这样?我在使用 DevC??


谢谢,我现在明白了,因为:

FirstName is a pointer to an array of char which is not being allocated by the malloc, only the pointer is being allocated and after you call free, it doesn't erase the memory, it just marks it as available on the heap to be over written later. – MattSmith

更新

我正在尝试模块化并将我的结构数组的创建放在一个函数中,但似乎没有任何效果。我正在尝试一些非常简单的事情,我不知道还能做什么。它和以前一样,只是另一个函数 loaddata 正在加载数据,在我需要做一些打印的方法之外。我怎样才能让它发挥作用?我的代码如下:

    # 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++,事情就会容易得多。标准模板库有一个名为 vector 的模板,可让您动态构建对象列表。

#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,事情会困难得多,是的,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;
}

关于c - 如何创建动态大小的结构数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13150630/

相关文章:

控制mplayer的C程序

c# - 3亿多条数据如何创建数组

c - 判断两个字符串是否由相同的字母组成

与 C 中的 sqrt() 函数混淆

c - gcc 预期标识符或 '(

Java问题,如何从未知对象中获取方法的值

mysql - DATE 在动态之间

css - float 流体图像左侧没有文字换行

ipad - 带有许多 UIImageViews 的 UIScrollView - 内存管理

android - 可移植 SD 卡 Android