C中的通用数据结构

时间:2013-12-11 23:22:14

标签: c data-structures generic-collections

有没有办法在C中创建通用数据结构并根据存储的数据类型使用函数,这种结构具有各种类型的数据,例如可以根据存储的数据打印。

例如,

假设我希望创建一个只有float的二进制搜索树,存储int。这样做的自然方法是使用int和float来创建枚举。它看起来像这样:

Typedef enum {INT, FLOAT} DataType;

Typedef struct node
{
    void *data;
    DataType t;
    struct node *left,
                *right;
}Node;

如果我想打印出来:

void printTree(Node *n)
{
    if (n != NULL)
    {
        if (n->t == INT)
        {
            int *a = (int *) n->data;
            printf("%d ", *a);
        }
        else
        {
            float *a = (float *) n->data;
            printf("%f ", *a);
        }

        printTree(n->left);
        printTree(n->right);
    }
}

没关系,但我想将另一种数据类型存储为堆栈,查询或其他内容。这就是为什么我创建了一个不依赖于特定数据类型的树,例如:

Typedef struct node
{
    void *data;
    struct node *left,
                *right;
}Node;

如果我想打印出来,我会使用回调函数,例如:

Node *printTree(Node *n, void (*print)(const void *))
{
    if (n != NULL)
    {
        print(n->data);
        printTree(a->left);
        printTree(a->right);
    }
}

但是当我尝试插入一个整数和一个浮点并将其打印出来时,它就会崩溃。我的问题是,有没有办法创建一个通用的数据结构,例程在一种情况下依赖于特定的数据类型,而另一种情况则不是,对于混合数据类型?在这种情况下,我应该创建一个存储int和float的存储结构,并在回调函数中使用类似于第一个打印代码的打印函数?

观察:我刚刚在结构中声明了一个节点并且在其上做了一切试图简化,但是想法是使用带有.h和.c的结构以及涉及数据结构的所有这些抽象。

3 个答案:

答案 0 :(得分:4)

我建议尝试以下内容。您会注意到Node包含tagged union,它允许指针类型,整数或浮点数。当Node是指针类型时,将调用自定义print函数,而在其他情况下,将使用相应的printf格式。

typedef enum {POINTER, INT, FLOAT} DataType;

typedef struct node
{
    DataType t;
    union {
        void *pointer;
        int integer;
        float floating;
    } data;
    struct node *left,
                *right;
} Node;

void printTree(Node *n, void (*print)(const void *))
{
    if (n != NULL) {
        switch (n->t) {
            case POINTER:
                print(n->data.pointer);
                break;
            case INT:
                printf("%d ", n->data.integer);
                break;
            case FLOAT:
                printf("%f ", n->data.floating);
                break;
        }
        printTree(a->left, print);
        printTree(a->right, print);
    }
}

答案 1 :(得分:1)

C不支持这种通用数据类型/结构。您可以选择一些选项:

  • 如果你有机会使用Clang作为编译器,那么overload functions in C.就有了语言扩展但你必须将参数强制转换为特定的类型,因此编译器知道哪个函数打电话。

  • 使用C ++

    • 虽然您仍然需要转换参数,但编译器知道他必须调用哪个名为print的可用函数。

    • 使用templates

  • 创建一个名为print的函数,其类似于

    struct data_info {
      void *data;
      enum_describing_type type;
    }
    

    print会切换并调用相应的printIntprintFloat等。

答案 2 :(得分:0)

uthash是头文件的集合,提供类型化哈希表,链表等实现,所有这些都使用C预处理器宏。