打印包含 void* 的链表元素
Printing elements of a linked list containing void*
我正在用 C 语言实现一个通用的双向链表,并且我已经编写了用于向前和向后遍历的函数。在这些函数中,我想打印列表中包含的数据,但由于它是通用的,所以我很难弄清楚如何做到这一点。显然我不能只 printf
使用 %d
或其他东西,因为列表可以包含任何数据类型。任何以不同方式处理此问题的建议将不胜感激,因为我已经考虑了很长一段时间而且我不知所措。谢谢!
您在为节点声明的 struct
中需要一个标记字段。为数据类型定义一个 enum
作为
enum {INT_TYPE, FLOAT_TYPE, DOUBLE_TYPE, CHAR_TYPE} type;
对于每种数据类型,您需要为 type
分配相应的枚举常量。在打印功能中,您必须检查 type
的值,然后使用适当的说明符。
你可以做很多事情。
例如,您可以存储的结构不仅包含元素数据的 void *
,而且还指示可能的数据类型,甚至只是 printf
所需的格式字符串object.
您还可以想到一个包含数据的 void *
的结构,以及一个允许您将数据转换为字符串的函数指针。这基本上是在 C 中最低限度地模拟 C++ 的多态性。
编辑: 正如 wickstopher 指出的那样,你只是没有得到 compile-time 类型安全。弄乱函数指针,你将有一个不合适的函数处理你的数据,可能导致你的程序出现段错误,运行 超过你的小猫,烧毁你的公寓,运行 带走你最小的 child 或者在你的厨房抽烟。
C 不支持任何类型的运行时类型检查,因此这是不可能的。参见 runtime determine type for C(类似问题)。
如果您想支持有限范围的数据类型,您可以考虑向您的节点结构添加一个枚举,但这不会让您获得真正的通用功能,并且在编译时无法强制执行。
假设你的节点有一个指向节点内容的void *
指针,在指向列表中下一个和前一个元素的指针中,提供一个打印节点的函数,例如
void PrintNode (Node_t *node, void (*fprint)(void *));
这个函数会获取节点的元素,然后调用用户提供的函数来实际打印节点的内容。
typedef struct stNode {
void *NodeContents;
struct stNode *prev;
struct stNode *next;
} Node_t;
void PrintNode (Node_t *node, void (*print)(void *))
{
if (node && node->NodeContents && print)
print(node->NodeContents);
}
我正在用 C 语言实现一个通用的双向链表,并且我已经编写了用于向前和向后遍历的函数。在这些函数中,我想打印列表中包含的数据,但由于它是通用的,所以我很难弄清楚如何做到这一点。显然我不能只 printf
使用 %d
或其他东西,因为列表可以包含任何数据类型。任何以不同方式处理此问题的建议将不胜感激,因为我已经考虑了很长一段时间而且我不知所措。谢谢!
您在为节点声明的 struct
中需要一个标记字段。为数据类型定义一个 enum
作为
enum {INT_TYPE, FLOAT_TYPE, DOUBLE_TYPE, CHAR_TYPE} type;
对于每种数据类型,您需要为 type
分配相应的枚举常量。在打印功能中,您必须检查 type
的值,然后使用适当的说明符。
你可以做很多事情。
例如,您可以存储的结构不仅包含元素数据的 void *
,而且还指示可能的数据类型,甚至只是 printf
所需的格式字符串object.
您还可以想到一个包含数据的 void *
的结构,以及一个允许您将数据转换为字符串的函数指针。这基本上是在 C 中最低限度地模拟 C++ 的多态性。
编辑: 正如 wickstopher 指出的那样,你只是没有得到 compile-time 类型安全。弄乱函数指针,你将有一个不合适的函数处理你的数据,可能导致你的程序出现段错误,运行 超过你的小猫,烧毁你的公寓,运行 带走你最小的 child 或者在你的厨房抽烟。
C 不支持任何类型的运行时类型检查,因此这是不可能的。参见 runtime determine type for C(类似问题)。
如果您想支持有限范围的数据类型,您可以考虑向您的节点结构添加一个枚举,但这不会让您获得真正的通用功能,并且在编译时无法强制执行。
假设你的节点有一个指向节点内容的void *
指针,在指向列表中下一个和前一个元素的指针中,提供一个打印节点的函数,例如
void PrintNode (Node_t *node, void (*fprint)(void *));
这个函数会获取节点的元素,然后调用用户提供的函数来实际打印节点的内容。
typedef struct stNode {
void *NodeContents;
struct stNode *prev;
struct stNode *next;
} Node_t;
void PrintNode (Node_t *node, void (*print)(void *))
{
if (node && node->NodeContents && print)
print(node->NodeContents);
}