C动态分配结构数组及其组件

C dynamically allocate struct array and its components

在 C 中动态分配结构数组及其组件的正确方法是什么?我设法做了一些有用的事情,但我有点怀疑它是否正确。 我有以下代码:
这是我需要动态分配的结构数组:

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

然后在我的主要功能中,我有这个:

    int nr_elem;
    scanf("%d",&nr_elem);
    Dictionary *dict;
    dict = init_Dictionary(nr_elem);

此外,当我完成对结构的处理后,如何释放已用内存?
编辑感谢大家快速而深入的回答!

程序设计不好,应该UI和算法分开。取而代之的是,您应该首先获取用户输入,然后将其存储在 2 个字符串中并将字符串作为参数传递给 init_Dictionary

至于分配,几乎是正确的。但是你忘了为空终止符分配space,它应该是:

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.

的调用相匹配

您的实现中存在错误: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);
}

对于每个分配,您需要再分配一个位置以允许在字符串末尾使用 [=12=](NULL 终止符)。

dict[i].wrong = malloc(strlen(wrong)*sizeof(char) +1 );
dict[i].right = malloc(strlen(right)*sizeof(char) +1);

要释放,首先需要释放数组中的所有指针rightwrong,然后释放主dict数组。或者,您可以在释放后将指针置空。

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