在C中创建一个用链表实现的通用堆栈
我想创建一个通用堆栈。我想用一个链表来实现它 我创建了这个结构堆栈\u l:在C中创建一个用链表实现的通用堆栈,c,data-structures,stack,linked-list,function-pointers,C,Data Structures,Stack,Linked List,Function Pointers,我想创建一个通用堆栈。我想用一个链表来实现它 我创建了这个结构堆栈\u l: typedef struct stack { void * data; void (*copy)(void *o); struct stack *next; } stack_l; 我有一些问题: 结构的第二个字段是指向函数的指针,用于复制新数据(在函数Push中通过参数传递)。 功能推送的原型为: 栈顶推(栈顶,void*d) 我将指针传递到函数副本的方式正确吗 我必须在函数Push
typedef struct stack
{
void * data;
void (*copy)(void *o);
struct stack *next;
} stack_l;
我有一些问题:
- 结构的第二个字段是指向函数的指针,用于复制新数据(在函数Push中通过参数传递)。 功能推送的原型为:
- 是否有必要创建一个函数NewStack(例如)来对结构的字段进行日化,或者最好只有一个Push函数,如果堆栈为空,则创建第一个元素,如果至少有一个元素,则在顶部添加新元素
- void*需要分配malloc吗
堆栈和堆栈不需要不同的标识符。现在,请回答您的问题:
您的Push
功能与stack\l
中的copy
字段的类型不兼容。如果你想在你的代码>结构> <代码>中包含一个指针(成员函数),使它看起来像C++,你仍然必须把你的对象传递给这些函数。
是的,您必须在某个地方实现您的功能,而这不能在struct stack
的定义范围内。这意味着您确实需要某种构造函数(如果愿意,您可以称之为newStack
)。构造函数必须至少初始化函数指针(如果您想保留它们)。如果您选择不保留这些函数指针,您可以按照您的建议,将初始化代码很好地放入push
例程中:
stack_l* stackPush(stack_l* head, void* content) {
// head might be NULL, meaning the stack is "empty" or it might be an actual pointer
// we don't care
stack_l* const front = malloc(sizeof(stack_l));
*front = (stack_l){.data = content, .next = head};
return front;
}
请注意,您必须明确说明空堆栈是什么。因此,为了清晰起见,您可能需要实现一个构造函数:
stack_l* stackCreateEmpty() {
retun NULL;
}
甚至可能是一个析构函数:
void stackDestroyEmpty(stack_l* s) {
assert(s == NULL && "Tried to destroy non-empty stack.");
}
对于您的最后一个问题:如上所述,您必须使用malloc
来获得容纳stack\l
对象的空间,除此之外,您不需要为void*
成员分配额外的空间,由于它是堆栈的一部分,显然我还创建了一个Pop函数来删除元素。谢谢你的评论。我只是不明白,如果将void*内容分配给.data=content的数据,是否有必要复制我的函数。也许我不理解。@Kyrol:你不必!正如我所说的,这只是为了清楚起见,所以堆栈实现的用户有一些接口需要保留。关于copy
:由于堆栈只存储void
指针(它存储指针的文本值,而不是指针指向的内容),因此不必实现复制功能,只需逐字复制指针即可。但是,如果确实要复制指针指向的对象,则必须为push函数提供一个自定义的copy参数,因为堆栈不可能知道其中存储了什么。希望这对您有所帮助,否则请询问。好的,很抱歉对构造函数产生误解!关于copy
:好的,如果我使用最大泛型属性编写函数,我不需要该函数。但是,如果我在main中调用Push,并且我想在数据中存储一个int(例如),我需要这个函数,不是吗?另一件事:为什么要将front声明为const
?@Kyrol:换句话说,如果堆栈拥有数据,那么必须提供一些复制数据的方法(即,知道void*
参数指向的语义和大小的东西)。但是,如果您希望堆栈只跟踪指针本身,则不需要复制机制。关于front
,我不打算更改指针,而且我有一个习惯,就是尽可能使所有内容都不可变且尽可能局部(可能是函数编程中的一些残余迷信)。这通常可以防止错误!