函数修改动态分配字符的二维数组*
所以,这里是我的逻辑:函数修改动态分配字符的二维数组*
这是一些文本:
char *text;
然后,这是课文的数组:
char **arr;
然后这些阵列的阵列是:
char ***arr2d;
如果我想一个函数来修改它,它需要接受它:
char ****arr2d;
和函数中使用它:
*arr2d = (e.g. allocate);
所以,如果我想创建二维数组一样这并使第一行,第一列只包含一个字母'a',那么为什么这不起作用?
#define COLUMNS 7
void loadTable(char ****table)
{
*table = (char ***) malloc(sizeof(char**));
if (!*table) {
printf("Allocation error for table rows.");
return;
}
*table[0] = (char**) malloc(COLUMNS * sizeof(char*));
if (!*table[0]) {
printf("Allocation error for table columns.");
return;
}
*table[0][0] = (char*) malloc(2 * sizeof(char));
*table[0][0][0] = (char)(97);
*table[0][0][1] = '\0';
}
int main()
{
char ***table;
loadTable(&table);
return 0;
}
您将只需要3 ***
做你的描述,而不是4 ****
。请注意,有些方法可以让您避免使用字符串数组的数组。还有很好的理由来避免数组的过度深入,而不仅仅是需要你分配的所有东西。这意味着对[m][c][re]alloc(.)
的每次调用只需拨打free(.)
。
但是,为了解决您的问题...
一般情况下,创建新的内存为单阵列以前分配的内存,你可以使用一个函数原型为:
char * ReSizeBuffer(char **str, size_t origSize);
如果说以前分配的缓冲区创建为:
char *buf = calloc(origSize, 1);
...使用情况如下所示:
char *tmp = {0};
tmp = ReSizeBuffer(&buf, newSize); //see implementation below
if(!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
///use new buf
...
那么,如果这种方式更适合焦炭的单一阵列,然后原型为字符串之前分配阵列分配新的内存可能是这样的:
char ** ReSizeBuffer(char ***str, size_t numArrays, size_t strLens);
哪里,如果说以前分配2D缓冲创建为:
char **buf = Create2DStr(size_t numStrings, size_t maxStrLen); //see implementation below
...的使用可能看起来像:
char **tmp = {0};
tmp = ReSizeBuffer(&buf, numStrings, maxStrLen);
if(!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
///use new buf
...
实现:
的ReSizeBuffer
实现。
char * ReSizeBuffer(char **str, size_t size)
{
char *tmp={0};
if(!(*str)) return NULL;
if(size == 0)
{
free(*str);
return NULL;
}
tmp = (char *)realloc((char *)(*str), size);
if(!tmp)
{
free(*str);
return NULL;
}
*str = tmp;
return *str;
}
的Create2DStr
实现可能是这样的:
char ** Create2DStr(size_t numStrings, size_t maxStrLen)
{
int i;
char **a = {0};
a = calloc(numStrings, sizeof(char *));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(maxStrLen + 1, 1);
}
return a;
}
唯一的评论将是,如果有一个愿望,保留'buf'的原始内容在'realloc'失败,你可以取消'free',取决于情况。另外,不需要'if {... return NULL;} else {buf = tmp; ...}'。如果失败发生,你已经*返回*,所以一个简单的'if {... return NULL;} buf = tmp; ...'就足够了,这些只是nits,所以'tmp =(char *)realloc ...'也是已知的[**我是否施放了malloc **的结果](http://*.com/q/605845/995714)nit ... –
@ DavidC.Rankin - 感谢您的详细回复! - 关于铸造...直到今年,当我的环境更新到它的最新版本(ANSI C99的实现)时,我从来没有任何问题没有施放[m] [c] [re] alloc返回)。现在我得到了一个令人讨厌的编译器警告。我还没有联系用bug报告生成这个编译器的公司,但是这让我怀疑他们是否让一些C++的esk行为进入我的珍贵'C99'系统。 – ryyker
@ DavidC.Rankin - 关于释放原始缓冲区 - 确实不是绝对必要的。但我把它放进去,因为如果一个请求是由一个调用函数完成的,那是因为需要更多的内存。如果该内存未被授予,则当尝试向同一buf写入更多内容时,调用者将失败,导致访问冲突或UB。我宁愿让返回成为一个明确的'NUL',以允许调用者知道避免这些失败模式。另一方面,我同意。我将简化陈述。再次感谢。 – ryyker
假设你需要4个指针是不正确的,如果你的愿望实现第二架原型机这必须扩大。确实,要更改字符串数组的内存参数,您需要传递该内存块的地址,但不需要4个星号即可完成此操作。 – ryyker
@ryyker我迷路了一下。所以在主函数中我需要通过地址来传递它,但接收函数只需要3颗星? – Bondy
是的,那是真的。请参阅下面的解释。 – ryyker