为数组使用动态内存分配

我怎么应该为数组使用动态内存分配?

例如,下面是一个数组,其中我从.txt文件中读取单个单词并在数组中逐字保存:

码:

char words[1000][15]; 

这里1000定义了数组可以保存的单词数,每个单词可以包含不超过15个字符。

现在我希望该程序应该为它计算的单词数量动态分配内存。 例如,.txt文件可能包含大于1000的单词。现在我希望程序应该计算单词数并相应地分配内存。

由于我们不能使用变量代替[1000],因此我对如何实现逻辑完全空白。 请帮助我这方面。

你使用指针。

具体来说,您使用指向地址的指针,并使用标准的c库函数调用,您要求操作系统扩展堆以允许您存储所需的内容。

现在,它可能会拒绝,你需要处理。

接下来的问题是 – 你如何要求2Darrays? 好吧,你要求一个指针数组,然后展开每个指针。

举个例子,考虑一下:

 int i = 0; char** words; words = malloc((num_words)*sizeof(char*)); if ( words == NULL ) { /* we have a problem */ printf("Error: out of memory.\n"); return; } for ( i=0; i 

这将为您提供一个二维数组,其中每个元素words[i]可以具有不同的大小,在运行时可以确定,就像单词的数量一样。

完成后,您需要通过循环遍历数组来free()所有结果内存:

 for ( i = 0; i < num_words; i++ ) { free(words[i]); } free(words); 

如果不这样做,您将创建内存泄漏。

你也可以使用calloc 。 不同之处在于调用约定和效果 - calloc将所有内存初始化为0malloc则不是。

如果需要在运行时resize,请使用realloc

  • 的malloc
  • 释放calloc
  • 的realloc
  • 自由

另外,重要的是,请注意我使用过的word_size + 1 。 C中的字符串是零终止的,这需要额外的字符,您需要考虑。 为了确保我记住这一点,我通常将变量word_size的大小设置为单词大小应该是什么(字符串的长度如我所期望的)并明确地将malloc中的+1保留为零。 然后我知道分配的缓冲区可以使用一串word_size字符。 不这样做也没关系 - 我这样做是因为我喜欢以明显的方式明确地解释零。

这种方法也有一个缺点 - 我最近明确将此视为一个传送的错误。 注意我写了(word_size+1)*sizeof(type) - 想象一下,我写了word_size*sizeof(type)+1 。 对于sizeof(type)=1这些是相同的,但是Windows经常使用wchar_t - 在这种情况下,你将为你的最后一个零而不是两个保留一个字节 - 它们是类型为零的终止元素,而不是单个零字节。 这意味着你将在读写时超支。

附录:按照你喜欢的方式做它,如果你要将缓冲区传递给依赖它们的东西,请注意那些零终止符。

虽然Ninefingers 使用指针数组提供了答案 ,但只要内部数组的大小是常量表达式,您也可以使用数组数组。 这个代码更简单。

 char (*words)[15]; // 'words' is pointer to char[15] words = malloc (num_words * sizeof(char[15]); // to access character i of word w words[w][i]; free(words); 

如果您打算使用C ++,STL对于动态分配非常有用,而且非常简单。 你可以使用std :: vector ..

如果您示例中的15是可变的,请使用其中一个可用答案(来自Ninefingers或John Boker或Muggen)。 如果1000是可变的,请使用realloc

 words = malloc(1000 * sizeof(char*)); // ... read 1000 words if (++num_words > 1000) { char** more_words = realloc(words, 2000 * sizeof(char*)); if (more_words) {printf("Too bad");} else {words = more_words;} } 

在我上面的代码中,常量2000是一个简化; 你应该添加另一个变量capacity来支持超过2000个单词:

 if (++num_words > capacity) { // ... realloc ++capacity; // will reallocate 1000+ words each time; will be very slow // capacity += 1000; // less reallocations, some memory wasted // capacity *= 2; // less reallocations but more memory wasted } 

如果你在C工作:

 #include  #include  #include  #define WORD_LEN 15 int resizeArray(char (**wordList)[WORD_LEN], size_t *currentSize, size_t extent) { int result = 1; char (*tmp)[WORD_LEN] = realloc(*wordList, (*currentSize + extent) * sizeof **wordList); if (tmp) { *currentSize += extent; *wordList = tmp; } else result = 0; return result; } int main(void) { char *data[] = {"This", "is", "a", "test", "of", "the", "Emergency", "Broadcast", "System", NULL}; size_t i = 0, j; char (*words)[WORD_LEN] = NULL; size_t currentSize = 0; for (i = 0; data[i] != NULL; i++) { if (currentSize <= i) { if (!resizeArray(&words, &currentSize, 5)) { fprintf(stderr, "Could not resize words\n"); break; } } strcpy(words[i], data[i]); } printf("current array size: %lu\n", (unsigned long) currentSize); printf("copied %lu words\n", (unsigned long) i); for (j = 0; j < i; j++) { printf("wordlist[%lu] = \"%s\"\n", (unsigned long) j, words[j]); } free(words); return 0; } 

以下是有关动态分配2d数组的一些信息:

http://www.eskimo.com/~scs/cclass/int/sx9b.html

 char ** words = malloc( 1000 * sizeof(char *)); int i; for( i = 0 ; i < 1000 ; i++) *(words+i) = malloc(sizeof(char) * 15); //.... for( i = 0 ; i < 1000 ; i++) free(*(words+i)); free(words); 

在现代C(C99)中,您还有一个额外的选择,可变长度数组,VLA,例如:

 char myWord[N]; 

原则上你也可以在两个方面做这样的事情,但如果你的尺寸太大,你可能会冒着堆栈溢出的风险。 在你的情况下,最简单的方法是使用指向这样一个数组的指针,并使用malloc / realloc来调整它们的大小:

 typedef char Word[wordlen]; size_t m = 100000; Word* words = malloc(m * sizeof(Word)); /* initialize words[0]... words[m-1] here */ for (size_t i = 0; i < m; ++i) words[i][0] = '\0'; /* array is too small? */ m *= 2; void *p = realloc(words, m*sizeof(Word)); if (p) words = p; else { /* error handling */ } . free(words); 

如果wordlen是常量或变量,只要将所有内容保存在一个函数中,此代码就可以工作(模数拼写错误)。 如果你想把它放在一个函数中,你应该声明你的函数

 void myWordFunc(size_t wordlen, size_t m, char words[m][wordlen]); 

这是长度参数必须首先为words声明所知。