在C中动态分配结构数组及其组件的正确方法是什么?我已经做了一些行之有效的事情,但是我对它是否正确表示怀疑。
我有以下代码:
这是我需要动态分配的struct数组:
k
这是我需要初始化结构数组时调用的函数:
typedef struct
{
char *wrong;
char *right;
}Dictionary;
然后在我的主要功能中,我有这个:
Dictionary *init_Dictionary(int nr_elem)
{
Dictionary *dict;
dict = malloc(nr_elem*sizeof(Dictionary));
for(int i=0; i<nr_elem; i++)
{
char wrong[101],right[101];
scanf("%s%s",wrong,right);
dict[i].wrong = malloc(strlen(wrong)*sizeof(char));
dict[i].right = malloc(strlen(right)*sizeof(char));
strcpy(dict[i].wrong,wrong);
strcpy(dict[i].right,right);
}
return dict;
}
此外,当我完成该结构的工作时,如何释放已使用的内存?
编辑,谢谢大家的快速而深入的解答!
答案 0 :(得分:3)
对于每个分配,您需要再分配一个位置,以允许在字符串末尾使用\0
(NULL终止符)。
dict[i].wrong = malloc(strlen(wrong)*sizeof(char) +1 );
dict[i].right = malloc(strlen(right)*sizeof(char) +1);
要释放,首先需要释放数组中的所有指针right
和wrong
,然后释放主dict
数组。 (可选)您可以在释放指针之后使指针为NULL。
Dictionary* freeDict(Dictionary *dict, int nr_elem)
{
for (int i=0; i<nr_elem; i++)
{
free(dict->wrong);
free(dict->right);
dict->wrong = NULL;
dict->right = NULL;
}
free (dict);
dict = NULL;
return dict;
}
//To call.
dict = free(dict, nr_elem);
答案 1 :(得分:2)
程序设计不好,应该将UI与算法分开。取而代之的是,您应该首先接受用户输入,然后将其存储在2个字符串中,并将字符串作为参数传递给init_Dictionary
。
关于分配,这几乎是正确的。但是您忘记为空终止符分配空间,它应该是:
dict[i].wrong = malloc(strlen(wrong)+1);
dict[i].right = malloc(strlen(right)+1);
与sizeof(char)
相乘是没有意义的,因为在所有系统上sizeof(char)
的定义始终为1
。
在生产质量的应用程序中,您必须始终检查每个malloc
的结果,然后处理错误。
您以与分配内存相同的方式释放内存,但是顺序相反,因为您需要dict
本身才有效,直到您释放其成员为止:
for(int i=0; i<nr_elem; i++)
{
free(dict[i].wrong);
free(dict[i].right);
}
free(dict);
根据经验,每次对malloc
的调用都必须与对free
的调用相匹配。
答案 2 :(得分:2)
您的实现中存在一个错误:strlen(s)
不计算终止的0字符,因此,尽管一个测试可能成功完成,但实际上这是一个UB。 strdup
可以为您服务;如果您没有标准库,只需为字符串副本分配内存时加1。甚至更好:将字符串长度计算一次,然后使用该值分配足够的字节并使用memcpy
复制内容。
否则,您的算法将非常有用(只要您真正需要字符串对数组即可,而无需使用诸如搜索索引之类的其他结构即可。)
要对其进行释放,请添加一个执行逐个元素的释放的析构函数,然后释放整个数组:
void destroy(Dictionary *dict, size_t nr_elem) {
for(size_t i = 0; i < nr_elem; ++i) {
free(dict[i].wrong);
free(dict[i].right);
}
free(dict);
}