C语言中的泛型数据结构

C语言中的泛型数据结构,c,data-structures,generic-collections,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,

是否有任何方法可以在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);
    }
}
如果我想打印出来,我使用回调函数,例如:

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的结构,并在回调函数中使用像第一个print代码中那样的print函数


观察:我只是在结构中声明了一个节点,并对其进行了简化,但我的想法是将该结构与.h和.c以及所有这些涉及数据结构的抽象一起使用。

我建议尝试以下内容。您会注意到,
节点
包含允许指针类型、整数或浮点数的。当
节点
是指针类型时,将调用自定义的
打印
函数,在其他情况下,将使用适当的
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);
    }
}

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

C不支持此类通用数据类型/结构。您可以选择以下几个选项:

  • 如果您有机会用作编译器,则有一个语言扩展,但必须将参数强制转换为特定类型,以便编译器知道要调用哪个函数

  • 使用C++

    • 尽管您仍然必须强制转换参数,因此编译器知道必须调用哪些可用函数,这些函数称为
      print

    • 使用

  • 创建一个名为
    print
    的函数

    struct data_info {
      void *data;
      enum_describing_type type;
    }
    
    print
    进行切换并调用相应的
    printInt
    printFloat


创建一个具有指针类型(
void*
)和非指针类型(
int
float
,等等)的联合体。我首先想到了模板,但后来注意到您需要C。。。我的错。回答你的问题,我不知道。您可以为数据存储创建多种类型的并集。一种想法是有一个包含两个成员的结构,一个用于存储的并集和一个用于数据类型的标志值。@TimCooper并集在处理(即打印)时可能会有问题。如何准确地通知结构中的数据类型?你需要一个额外的标志值。我认为唯一安全的方法是使用一堆预处理器的东西。。这就是C++的发明:)本质上,C不支持基于数据类型的分支动作(允许不同的函数集)?我刚完成打字,看到了你的相同答案…嗯+1这是最好的了。如果你编码了C++,你可以调用一个通用的代码<代码> ->打印()/<代码>,而不知道它的类型,但是这是一个故事的另一天。但是这不仅解决了这个特殊的情况,我的意思是它只能打印3个数据类型,不是吗?谢谢。它将扩展到任何其他类型的例程,包括特定类型的数据,对吗?