我如何创build一个dynamic大小的结构数组?

我知道如何创build一个结构数组,但具有预定义的大小。 但是,有没有办法创build一个dynamic数组结构,使数组可以变大?

例如:

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.我假设我不知道有多less数据来进入我的程序。 在我上面定义的结构体中,我可以创build第一个“索引”:

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

不过,我想dynamic添加元素到数组之后。 我希望我能够清楚地描述问题所在。 主要的挑战是dynamic添加第二个领域,至less这是目前的挑战。


不过,我已经取得了一些进展:

  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我得到一个错误,这是我想要的。 那么至less在我的编译器上,这个自由函数是不行的呢? 我正在使用DevC?


谢谢,我现在明白了:

FirstName是指向一个char数组的指针,它不是由malloc分配的,只有指针正在被分配,并且在你释放之后,它不会擦除内存,它只是标记为在堆上可用稍后写。 – 马特·史密斯

PS对不起,长的网页,我想我现在已经习惯了这个论坛。

我有问题。 我不知道下一步该怎么做。 请帮助别人。 我试图模块化,把我的结构数组的创build在一个函数,但它不工作,我已经试过了一切,似乎没有任何工作。 我正在尝试一些非常简单的事情,我不知道还有什么要做。 它和前面一样,只是另外一个函数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; }// 

这个简单的testing代码崩溃了,我不知道为什么。 错误在哪里?

你已经把它标记为C ++和C

如果你使用C ++,事情要简单得多。 标准模板库有一个称为向量的模板,允许您dynamicbuild立一个对象列表。

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

如果要dynamic分配数组,可以使用stdlib.h malloc

如果你想使用你的words struct分配一个100个元素的数组,请尝试以下操作:

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

你要分配的内存大小被传入malloc ,然后它将返回一个voidvoid* )types的指针。 在大多数情况下,你可能想把它转换成你想要的指针types,在这种情况下是words*

这里使用sizeof关键字来查找struct这个words的大小,然后将这个大小乘以你想要分配的元素的数量。

一旦你完成了,一定要使用free()释放你使用的堆内存,以防止内存泄漏 :

 free(array); 

如果你想改变分配数组的大小,你可以尝试像其他人所说的那样使用realloc ,但是请记住,如果你做了很多realloc你最终可能会分割内存 。 如果你想dynamic调整数组的大小,以保持程序的内存占用less,最好不要做太多的重新分配。

这看起来像一个学术演习,不幸的是使得它更难,因为你不能使用C ++。 基本上你必须pipe理一些分配的开销,并跟踪已经分配了多less内存,如果你以后需要调整它的大小。 这就是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)); 

请记住,在你的例子中,你只是分配一个指向字符的指针,你仍然需要分配string本身,更重要的是在最后释放它。 所以这段代码为char分配了100个指针,然后把它重新调整到76,但是不会自己分配这个string。

我怀疑你实际上是想分配一个与上面非常相似的string中的字符数,但是把字改成char。

编辑:另外请记住,创build函数来执行常见任务和强制执行一致性是非常有意义的 ,所以不要随处复制代码。 例如,您可能需要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); 

编辑:至于resize的结构,这是相同的resize的字符数组。 但是,不同之处在于,如果将结构数组设置得更大,则应该将新数组项初始化为NULL。 同样,如果你使struct数组变小,你需要在删除项目之前进行清理 – 这是在调整结构数组之前已经分配的空闲项(只有已分配的项)。 这是我build议创build帮助函数来帮助pipe理的主要原因。

 // 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 ++标记你的问题…

另一个选项是链接列表 。 您需要分析程序如何使用数据结构,如果您不需要随机访问,则可能比重新分配更快。

这是我将如何在C ++中做到这一点

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

任何结构或c ++类使用相同的主体。

你上次更新的代码不应该编译,更不用说运行了。 您将&x传递给LoadData。 &x具有**字的types,但LoadData需要单词*。 当你调用一个指向堆栈的指针时,它会崩溃。

解决它的方法是将LoadData更改为接受单词**。 这个摇摆,你实际上可以修改main()中的指针。 例如,realloc调用看起来像

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

这与“num”是int *而不是int相同。

除此之外,你需要真正弄清楚string是如何存储的。 为char *指定一个常量string(如str2 =“marley \ 0”)是允许的,但它很less是正确的解决scheme,即使在C.

还有一点:除非你真的需要在string的末尾有两个0,否则不需要有“marley \ 0”。 编译器将每个string文字的末尾加上0。

对于testing代码:如果要修改函数中的指针,则应该将“指针指针”传递给该函数。 更正的代码如下:

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

如果你想dynamic增长数组,你应该使用malloc()dynamic分配一些固定数量的内存,然后在你用完时使用realloc()。 一个常见的技术是使用指数增长函数,以便分配一些小的固定数量,然后通过复制分配的数量使数组增长。

一些示例代码将是:

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

退房mallocrealloc