微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带标题的通用结构的实现

如何解决带标题的通用结构的实现

我有点困惑。 练习很长,所以我希望我写了与我的问题相关的所有内容我有一个给定的头文件(其中的一部分):

typedef void *(*copy_element)(const void *);
typedef void *(*free_element)(void **);

typedef struct group {
    size_t group_size;
    void **data;
    copy_element copy_element_func;
    free_element free_element_func;
} group;

group *group_alloc(copy_element copy_element_func,free_element free_element_func);
void group_free(group **p);
int add(group *group,const void *value);

我需要将 group.c 实现为通用结构。 我的问题是如何为 **data 实现 add 和 alloc 函数? 对于已知类型,我会使用 malloc 和 realloc 以及类型的大小,但在这里我不确定该怎么做。

group *group_alloc() {
    group *p = malloc(sizeof(group))
    if(p == NULL) {
        //
    }
    p->group_size = 0;

    void **ptr = malloc(sizeof(void*));
    p->data = ptr;
    return p;
}

在练习中,Group 应该包含一个动态的值数组。

谢谢!

解决方法

事实上,你不应该关心元素的大小和类型,因为调用者应该提供 2 个函数来处理这些元素的复制和释放,所以你可以在 group函数级别将它们作为完全不透明的指针处理。

这是一个可能的实现。此代码还包含一个演示如何处理空终止字符串的小演示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef void *(*copy_element)(const void *);
typedef void *(*free_element)(void **);

typedef struct group {
    size_t group_size;
    void **data;
    copy_element copy_element_func;
    free_element free_element_func;
} group;

group *group_alloc(copy_element copy_element_func,free_element free_element_func);
void group_free(group **p);
int add(group *group,const void *value);

/***
Allocate a new group that will use the 2 provided functions.
The group will be initially empty
*/
group *group_alloc(copy_element copy_element_func,free_element free_element_func) {
    group * g = malloc(sizeof(*g));
    g->group_size = 0;
    g->data = NULL;
    g->copy_element_func = copy_element_func;
    g->free_element_func = free_element_func;
    return g;
}

/*********
* Add a new element to a group.
* Will use the copy_element_func member to build a copy of the element
* This implementation returns the number of elements in the group
*/
int add(group *group,const void *value) {
    size_t sz = group->group_size + 1;  // do not change anything on alloc error
    void **data = realloc(group->data,sz * sizeof(void *));
    if (data == NULL) {  // allocation error
        return 0;
    }
    // use copy_element_func to build a copy of the element
    data[sz - 1] = group->copy_element_func(value);
    group->group_size = sz;
    group->data = data;
    return (int) sz;
}

/******************
* Free a group.
* First free all elements of the group (using the free_element_func member)
* and then the group itself
*/
void group_free(group **p) {
    group *g = *p;
    if (g != NULL) {
        for (int i = 0; i < g->group_size; i++) {
            // again use free_element_func that should be able to free an element
            g->free_element_func(g->data + i);
        }
        free(g);
    }
    *p = NULL;
}

// Example functions for null terminated strings
void * copy_string(const void *input) {
    return strdup(input);
}

void * free_string(void **str) {
    free(*str);
    *str = NULL;
    return *str;
}

// demo code
int main() {
    group *g = group_alloc(&copy_string,&free_string);
    int i = add(g,"foo");
    printf("%d\n",i);   // should display 1
    i = add(g,"bar");
    printf("%d\n",i);   // should display 2
    for (i = 0; i < g->group_size; i++) {
        printf("%s\n",((char **)g->data)[i]);  // should display foo then bar
    }
    group_free(&g);
    printf("%p\n",g);   // should display a NULL pointer
    return 0;
}

免责声明:这段代码盲目地假设了 strdup 函数的可用性,而它是可选的并且不测试分配错误...

,

根据您的描述,我认为您应该执行以下操作:

group_size 成员保存组中数据条目的数量。

data 成员是指向添加到组中的对象的指针数组。

通过结构和函数定义的这种组合,除了将指向对象的指针添加到组中的 data 数组之外,您无能为力。

group_alloc 函数中,您只需为 group 对象本身分配内存并初始化其成员:

group *group_alloc(copy_element copy_element_func,free_element free_element_func){
    group *ret = malloc(sizeof(*ret));
    if(ret == NULL){
        return(NULL);
    }
    ret->group_size = 0; //initially the group holds no pointers to objects
    ret->data = NULL;
    ret->free_element_func = free_element_func;
    ret->copy_element_func = copy_element_func;
    return(ret);
}

当要添加对象时,会调用 add 函数。 调用者传递应该存储对象的 group 和指向该对象的指针。您必须为 data 数组中的另一个指针腾出空间:

int add(group *group,const void *value){
    void **newData = realloc(group->data,(group->data_size + 1) * sizeof(*group->data)); //Grow the data array by one to store an additional pointer. 
    //realloc may return NULL,in that case an error occured,but you don't want to overwrite your existing data pointer
    if(newData == NULL){
        return(-1); //return -1 to indicate an error occured
    }
    group->data = newData;
    group->data[group->data_size] = value; //store the pointer to the object in the last array field
    group->data_size++; //increment data_size
    return(0); //return 0 to indicate success
}

我有点怀疑这个结构的用处,因为你可以将指向任意数据的指针添加到组中,关于什么样的数据以及它是否必须在以后被释放的零信息被存储。您可以添加一堆指向静态对象的指针和一堆指向动态分配对象的指针,而您将不知道必须释放哪些对象。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。