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

时间:2017-06-19 00:17:14

标签: c pointers struct

我有这个结构:

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

所以下面的strcut有一个int数据,我希望函数接受CopyFunction,它实际上是一个接受void *并返回void *的函数的指针,我希望我的函数在第一个中获取数据的副本节点连接到第二个数据的副本,现在我希望数据不仅是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;
}

我认为如果我改变并且不使用始终结构节点*会更好我想拥有:typedef struct node_t * Node;

1 个答案:

答案 0 :(得分:1)

concatLists(..., (copy_function)copyInt)

提供所有“方法”(cmpCopyFunction)作为参数变得非常快。为什么不创建一个List“对象”,它不仅包含指向头部和尾部的指针,还包含将列表一般化的“方法”。

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