我知道如何创建一个结构数组但具有预定义的大小.但是有没有办法创建一个动态的结构数组,以便数组可以变得更大?
例如:
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在哪里?
你已将其标记为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; }
如果要动态分配数组,可以使用malloc
from stdlib.h
.
如果要使用words
结构分配包含100个元素的数组,请尝试以下操作:
words* array = (words*)malloc(sizeof(words) * 100);
传入要分配的内存大小,malloc
然后返回一个type void
(void*
)指针.在大多数情况下,您可能希望将其转换为您想要的指针类型,在本例中为words*
.
该sizeof
关键字用在这里找出的大小words
结构,那么大小是由要分配的元素个数相乘.
完成后,请务必使用free()
以释放您使用的堆内存以防止内存泄漏:
free(array);
如果要更改已分配数组的大小,可以尝试使用realloc
其他人提到的,但请记住,如果执行多次操作,realloc
最终可能会破坏内存.如果要动态调整阵列大小以便为程序保留较低的内存占用,最好不要执行太多realloc
的操作.
这看起来像一个学术练习,不幸的是,由于你不能使用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);