当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何创建动态大小的结构数组?》经验,为你挑选了3个好方法。

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

例如:

    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我得到一个错误,这是我想要的.那么免费功能是不起作用的,至少在我的编译器上呢?我正在使用DevC ??


谢谢,我理解现在由于:

FirstName是一个指向char数组的指针,它没有被malloc分配,只有指针正在被分配,在你调用free之后,它不会擦除内存,它只是将它标记为堆上的可用结束后来写的.- 马特·史密斯

更新

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

    # include 
    # include 
    # include 
    # include 

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

这个简单的测试代码崩溃,我不明白为什么.这个bug在哪里?



1> Tom..:

你已将其标记为C++以及C.

如果你正在使用C++,那么事情会容易得多.标准模板库有一个名为vector的模板,允许您动态构建对象列表.

#include 
#include 

typedef std::vector 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 
#include 

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   
#include 

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


@thaggie:你已经倒退了; C不需要强制转换,但C++可以.

2> coobird..:

如果要动态分配数组,可以使用mallocfrom stdlib.h.

如果要使用words结构分配包含100个元素的数组,请尝试以下操作:

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

传入要分配的内存大小,malloc然后返回一个type void(void*)指针.在大多数情况下,您可能希望将其转换为您想要的指针类型,在本例中为words*.

sizeof关键字用在这里找出的大小words结构,那么大小是由要分配的元素个数相乘.

完成后,请务必使用free()以释放您使用的堆内存以防止内存泄漏:

free(array);

如果要更改已分配数组的大小,可以尝试使用realloc其他人提到的,但请记住,如果执行多次操作,realloc最终可能会破坏内存.如果要动态调整阵列大小以便为程序保留较低的内存占用,最好不要执行太多realloc的操作.



3> Ryan..:

这看起来像一个学术练习,不幸的是,由于你不能使用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个指向char的指针,然后将其大小调整为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);

编辑:就调整结构大小而言,它与调整char数组的大小完全相同.但是,区别在于如果使struct数组更大,则应该将新数组项初始化为NULL.同样,如果使struct数组变小,则需要在删除项之前进行清理 - 这是在调整struct数组大小之前已分配的空闲项(以及仅分配的项).这是我建议创建帮助函数来帮助管理它的主要原因.

// 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);

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有