首页 文章

如何用void *数据创建一个struct?

提问于
浏览
-1

我有这个结构:

struct node
{
    int data;
    struct node *next;
};

所以下面的strcut有一个int数据,我希望函数接受CopyFunction,它实际上是一个接受void *并返回void *的函数的指针,我希望我的函数在连接到的第一个节点中获取数据的副本复制f第二个数据,现在我希望数据不仅仅是int我想在任何数据上使用这个函数所以我使用CopyFunction指向一个函数的指针,因为我所说的接受void * ...我怎么能用这在函数下面...例如,如果我想将结构更改为:

struct node
    {
        Element data;
        struct node *next;
    };

typedef void* Element;

typedef Element (*copy_function) (Element);


struct node * concatLists( struct node *head1, struct node *head2, int cmp( struct node *),copy_function CopyFunction)
{
    struct node *head = NULL;
    struct node **current = &head;

    for ( ; head1 != NULL; head1 = head1->next )
    {
        if ( cmp( head1 ) )
        {
            *current = malloc( sizeof( struct node ) );
            ( *current )->data = CopyFunction(head1->data);
            ( *current )->next = NULL;
            current = &( *current )->next;
        }
    }

    for ( ; head2 != NULL; head2 = head2->next )
    {
        if ( cmp( head2 ) )
        {
            *current = malloc( sizeof( struct node ) );
            ( *current )->data = CopyFunction(head2->data);
            ( *current )->next = NULL;
            current = &( *current )->next;
        }
    }

然后,如果我有一个int结构,我可以使用此函数与int的复制函数,如下所示:

static void* copyInt(void* num){
    int* newInt=malloc(sizeof(*newInt));
    *newInt=*(int*)num;
    return newInt;
}

另外我认为如果我改变并且不使用总是struct node *我会想要更好:typedef struct node_t * Node;

1 回答

  • 1
    concatLists(..., (copy_function)copyInt)
    

    提供所有"methods"( cmpCopyFunction )作为参数变得非常快 . 为什么不创建 List "object",它不仅包含指向头部和尾部的指针,而且还包含"methods"以对列表进行泛化 .

    cmp 可能是一个比较函数(这意味着它应该采用两个参数),这意味着您可能正在尝试合并排序列表 . 好吧,这里的代码使用通用列表实现来做到这一点 . (我想我也可以制作 mallocfree 也可插拔 . )

    #include <stdio.h>
    #include <stdlib.h>
    
    // -----
    // ListNode type declarations.
    
    typedef struct ListNode {
        void* data;
        struct ListNode* prev;
        struct ListNode* next;
    } ListNode;
    
    // -----
    // ListType type declarations.
    
    typedef void* (* Allocator    )(size_t);
    typedef void  (* Deallocator  )(void*);
    typedef void  (* FreeFunction )(void*);
    typedef int   (* CmpFunction  )(void*, void*);
    typedef void* (* CopyFunction )(void*);
    
    typedef struct {
        Allocator    malloc;
        Deallocator  free;
        FreeFunction free_data;
        CmpFunction  cmp;
        CopyFunction copy;
    } ListType;
    
    // -----
    // List type declarations.
    
    typedef struct {
        const ListType* list_type;
        ListNode* head;
        ListNode* tail;
    } List;
    
    typedef void (*ListVisitor)(void*);
    
    // -----
    // ListDataInt definitions.
    
    static void* ListDataInt_new(int i) {
        int* ip = malloc(sizeof(int));
        *ip = i;
        return ip;
    }
    
    static void ListDataInt_free_data(int* ip) {
        free(ip);
    }
    
    static int ListDataInt_cmp(const int* ap, const int* bp) {
        if (*ap < *bp) return -1;
        if (*ap > *bp) return +1;
        return 0;
    }
    
    static int* ListDataInt_copy(const int* orig_ptr) {
        int* new_ptr = malloc(sizeof(int));
        *new_ptr = *orig_ptr;
        return new_ptr;
    }
    
    static const ListType ListDataInt_list_type = {
        malloc,
        free,
        (FreeFunction)ListDataInt_free_data,
        (CmpFunction)ListDataInt_cmp,
        (CopyFunction)ListDataInt_copy
    };
    
    // -----
    // ListNode definitions.
    
    static ListNode* ListNode_new(List* list, void* data) {
        const ListType* list_type = list->list_type;
    
        ListNode* node = list_type->malloc(sizeof(ListNode));
        node->data = data;
        node->prev = NULL;
        node->next = NULL;
        return node;
    }
    
    static void ListNode_free(List* list, ListNode* node) {
        const ListType* list_type = list->list_type;
    
        list_type->free_data(node->data);
        list_type->free(node);
    }
    
    // -----
    // List definitions.
    
    static List* List_new(const ListType* list_type) {
        List* list = list_type->malloc(sizeof(List));
        list->list_type = list_type;
        list->head = NULL;
        list->tail = NULL;
        return list;
    }
    
    static void List_free(List* list) {
        ListNode* next = list->head;
        while (next != NULL) {
            ListNode* node = next;
            next = node->next;
            ListNode_free(list, node);
        }
    
        list->list_type->free(list);
    }
    
    static void List_push(List* list, ListNode* node) {
        if (list->tail == NULL) {
            list->head = list->tail = node;
        } else {
            list->tail->next = node;
            node->prev = list->tail;
            list->tail = node;
        }
    }
    
    static void List_push_data(List* list, void* data) {
        List_push(list, ListNode_new(list, data));
    }
    
    static void List_visit(List* list, ListVisitor visitor) {
        for (ListNode* node = list->head; node != NULL; node = node->next) {
            visitor(node->data);
        }
    }
    
    // -----
    // Main program.
    
    static List* merge_sorted_lists(List* list1, List* list2) {
        const ListType* list_type = list1->list_type;
    
        List* new_list = List_new(list_type);
    
        ListNode* src1 = list1->head;
        ListNode* src2 = list2->head;
        while (src1 != NULL && src2 != NULL) {
            int cmp = list_type->cmp(src1->data, src2->data);
            if (cmp <= 0) {
                List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
                src1 = src1->next;
            }
    
            if (cmp >= 0) {
                List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
                src2 = src2->next;
            }
        }
    
        while (src1 != NULL) {
            List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
            src1 = src1->next;
        }
    
        while (src2 != NULL) {
            List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
            src2 = src2->next;
        }
    
        return new_list;
    }
    
    static void dumper(const int* ip) {
        printf("%d\n", *ip);
    }
    
    int main(void) {
        List* sorted_int_list1 = List_new(&ListDataInt_list_type);
        List_push_data(sorted_int_list1, ListDataInt_new(4));
        List_push_data(sorted_int_list1, ListDataInt_new(6));
        List_push_data(sorted_int_list1, ListDataInt_new(8));
    
        List* sorted_int_list2 = List_new(&ListDataInt_list_type);
        List_push_data(sorted_int_list2, ListDataInt_new(5));
        List_push_data(sorted_int_list2, ListDataInt_new(7));
        List_push_data(sorted_int_list2, ListDataInt_new(9));
    
        List* merged_sorted_int_list =
            merge_sorted_lists(sorted_int_list1, sorted_int_list2);
    
        List_visit(merged_sorted_int_list, (ListVisitor)dumper);
    
        List_free(sorted_int_list1);
        List_free(sorted_int_list2);
        List_free(merged_sorted_int_list);
        return 0;
    }
    

    测试:

    $ gcc -Wall -Wextra -pedantic --std=c99 -o a a.c && a
    4
    5
    6
    7
    8
    9
    

相关问题