通用链表? 我想知道是否有可能在C中使用链表的泛型函数,(我不想在C++中做,但是在C中)例子: struct first_struct { struct first_struct *next; int a; int b; }; struct second_struct { struct second_struct *next; int a; int b; int c; // just one more variable than first-struct };
我是否强制每次为两个列表创建一个函数:通用链表? 我想知道是否有可能在C中使用链表的泛型函数,(我不想在C++中做,但是在C中)例子: struct first_struct { struct first_struct *next; int a; int b; }; struct second_struct { struct second_struct *next; int a; int b; int c; // just one more variable than first-struct };,c,linked-list,polymorphism,C,Linked List,Polymorphism,我是否强制每次为两个列表创建一个函数: add_node(struct first_struct *mystruct)// doesn't matter the function here juste let's assume they add correctly a node add_node1(struct second_struct *mystruct) //and so on each time i want to make some others function always mak
add_node(struct first_struct *mystruct)// doesn't matter the function here juste let's assume they add correctly a node
add_node1(struct second_struct *mystruct)
//and so on each time i want to make some others function always make them twice
或者有更好的方法吗?更好的方法是抽象出链接处理(是什么使一个结构成为一个列表节点),然后用节点结构启动每个列表结构,重新使用它 像这样:
struct list_node {
struct list_node *next;
};
struct first_struct {
struct list_node list_node;
int a;
int b;
};
struct second_struct {
struct list_node list_node;
int a;
int b;
int c;
};
然后生成处理(指向)struct list\u节点的指针的列表函数
这通常被称为“入侵列表”,因为它要求应用程序级数据结构“知道”可以将其放入列表中。这也意味着一个结构的实例一次只能在一个列表中
另一种方法是创建一个列表库,它只处理指向数据的指针(
void*
),这消除了限制,但带来了其他限制(更多的堆分配,当数据很小时会很烦人)。我个人实现了一个通用链表:它通过提供一个函数来比较两个节点,还有一个可选的销毁节点的功能(释放字符串、关闭文件等)
#包括
#包括
类型定义结构链接{
作废*数据;
结构链接*上一个;
结构链接*下一步;
}联系美国;
类型定义结构列表{
链接头;
链尾;
尺寸链接;
/*函数指针*/
int(*数据比较)(常数无效*数据1,常数无效*数据2);
void(*Data_Destructor)(void*Data);
}名单;;
#定义列表构造函数(f_比较,f_析构函数){.head=NULL\
.tail=NULL\
.nbLink=0\
.Data\u Compare=f\u compar\
.Data_析构函数=f_析构函数}
void List_构造函数(List_*self,int(*数据比较)(const void*data1,const void*data2),void(*数据析构函数)(void*Data));
无效列表析构函数(列表自身);
bool列表添加(列表*自身,无效*数据);
void*List\u RemoveByLink(List\u*self,link\u*link);
作废*列表\删除数据(列表\自身,作废*数据);
无效*列表移除条件(列表自身,布尔(*数据条件)(常量无效*数据));
无效列表链接(列表自身、链接);
作废列表*数据(列表*自身,作废*数据);
无效列表条件(列表自身,布尔(*数据条件)(常量无效*数据));
无效列表排序(列表自身);
作废列表合并(列表到,列表从);
作废清单(清单本身);
这样,您就可以在列表中添加任何您想要的内容。只需小心使用propre comparison函数和destroy函数。在结构中使用void指针可以非常轻松地实现通用链表 以下是我创建的此类列表的示例: list.c
#include <stdlib.h>
#include "list.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
void listNew(list* list, unsigned int elementSize, freeMemory freeFn,
printList print) {
list->numOfElem = 0;
list->freeFn = freeFn;
list->pr = print;
list->head = NULL;
list->sizeOfElem = elementSize;
}
node * listPushFront(list *list, void* data) {
node *listNode = (node*)malloc(sizeof(node));
if (listNode == NULL) {
return NULL;
}
listNode->object = malloc(sizeof(list->sizeOfElem));
if (listNode->object == NULL) {
return NULL;
}
memcpy(listNode->object, data, list->sizeOfElem);
listNode->pNext = list->head;
list->head = listNode;
list->numOfElem++;
return listNode;
}
void listDestroy(list *list)
{
node *current;
while (list->head != NULL) {
current = list->head;
list->head = current->pNext;
if (list->freeFn) {
list->freeFn(current->object);
}
free(current->object);
free(current);
}
}
void listPrint(list *l) {
node* temp = l->head;
int i = 0;
if (temp == NULL) {
printf("\nEmpty list.");
return;
}
while (temp) {
printf("\nPrint element %d", i);
l->pr(temp->object);
temp = temp->pNext;
i++;
}
}
#include <stdlib.h>
#include "list.h"
#include <stdio.h>
#include <string.h>
typedef struct _TLV {
unsigned int tag;
unsigned int length;
unsigned char* value;
}TLV;
void listFree(void* data) {
TLV** ptr = (TLV**)data;
free((*ptr)->value);
}
void Print(void* data) {
TLV** ptr = (TLV**)data;
printf("\nTag = %d", (*ptr)->tag);
printf("\nLength = %d", (*ptr)->length);
printf("\nValue = ");
for (int i = 0; i < (*ptr)->length; i++) {
printf("%d", (*ptr)->value[i]);
}
}
TLV* allocateTLV(unsigned int tag, unsigned int length, unsigned char*
value) {
TLV* elem = (TLV*)malloc(sizeof(TLV));
if (elem == NULL) {
return NULL;
}
elem->tag = tag;
elem->length = length;
elem->value = (unsigned char*)malloc(length);
if (value == NULL) {
return NULL;
}
memcpy(elem->value, value, length);
return elem;
}
int main()
{
list l;
TLV* tag;
unsigned char test2[2] = { 1,2 };
unsigned char test3[3] = { 1,2,3 };
unsigned char test4[4] = { 1,2,3,4};
listNew(&l, sizeof(TLV*), listFree, Print);
tag = allocateTLV(2, sizeof(test2), test2);
if (tag != NULL) {
listPushFront(&l, &tag);
}
tag = allocateTLV(3, sizeof(test3), test3);
if (tag != NULL) {
listPushFront(&l, &tag);
}
tag = allocateTLV(4, sizeof(test4), test4);
if (tag != NULL) {
listPushFront(&l, &tag);
}
listPrint(&l);
listDestroy(&l);
return 0;
}
main.c
#include <stdlib.h>
#include "list.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
void listNew(list* list, unsigned int elementSize, freeMemory freeFn,
printList print) {
list->numOfElem = 0;
list->freeFn = freeFn;
list->pr = print;
list->head = NULL;
list->sizeOfElem = elementSize;
}
node * listPushFront(list *list, void* data) {
node *listNode = (node*)malloc(sizeof(node));
if (listNode == NULL) {
return NULL;
}
listNode->object = malloc(sizeof(list->sizeOfElem));
if (listNode->object == NULL) {
return NULL;
}
memcpy(listNode->object, data, list->sizeOfElem);
listNode->pNext = list->head;
list->head = listNode;
list->numOfElem++;
return listNode;
}
void listDestroy(list *list)
{
node *current;
while (list->head != NULL) {
current = list->head;
list->head = current->pNext;
if (list->freeFn) {
list->freeFn(current->object);
}
free(current->object);
free(current);
}
}
void listPrint(list *l) {
node* temp = l->head;
int i = 0;
if (temp == NULL) {
printf("\nEmpty list.");
return;
}
while (temp) {
printf("\nPrint element %d", i);
l->pr(temp->object);
temp = temp->pNext;
i++;
}
}
#include <stdlib.h>
#include "list.h"
#include <stdio.h>
#include <string.h>
typedef struct _TLV {
unsigned int tag;
unsigned int length;
unsigned char* value;
}TLV;
void listFree(void* data) {
TLV** ptr = (TLV**)data;
free((*ptr)->value);
}
void Print(void* data) {
TLV** ptr = (TLV**)data;
printf("\nTag = %d", (*ptr)->tag);
printf("\nLength = %d", (*ptr)->length);
printf("\nValue = ");
for (int i = 0; i < (*ptr)->length; i++) {
printf("%d", (*ptr)->value[i]);
}
}
TLV* allocateTLV(unsigned int tag, unsigned int length, unsigned char*
value) {
TLV* elem = (TLV*)malloc(sizeof(TLV));
if (elem == NULL) {
return NULL;
}
elem->tag = tag;
elem->length = length;
elem->value = (unsigned char*)malloc(length);
if (value == NULL) {
return NULL;
}
memcpy(elem->value, value, length);
return elem;
}
int main()
{
list l;
TLV* tag;
unsigned char test2[2] = { 1,2 };
unsigned char test3[3] = { 1,2,3 };
unsigned char test4[4] = { 1,2,3,4};
listNew(&l, sizeof(TLV*), listFree, Print);
tag = allocateTLV(2, sizeof(test2), test2);
if (tag != NULL) {
listPushFront(&l, &tag);
}
tag = allocateTLV(3, sizeof(test3), test3);
if (tag != NULL) {
listPushFront(&l, &tag);
}
tag = allocateTLV(4, sizeof(test4), test4);
if (tag != NULL) {
listPushFront(&l, &tag);
}
listPrint(&l);
listDestroy(&l);
return 0;
}
#包括
#包括“list.h”
#包括
#包括
类型定义结构{
无符号整数标记;
无符号整数长度;
无符号字符*值;
}TLV;
void listFree(void*数据){
TLV**ptr=(TLV**)数据;
自由((*ptr)->值);
}
作废打印(作废*数据){
TLV**ptr=(TLV**)数据;
printf(“\nTag=%d”,(*ptr)->标记);
printf(“\n长度=%d”,(*ptr)->长度);
printf(“\nValue=”);
对于(int i=0;i<(*ptr)->长度;i++){
printf(“%d”)(*ptr)->值[i];
}
}
TLV*allocateTLV(无符号整数标记、无符号整数长度、无符号字符*
价值){
TLV*elem=(TLV*)malloc(sizeof(TLV));
if(elem==NULL){
返回NULL;
}
元素->标签=标签;
元素->长度=长度;
元素->值=(无符号字符*)malloc(长度);
如果(值==NULL){
返回NULL;
}
memcpy(元素->值、值、长度);
返回元素;
}
int main()
{
清单l;
TLV*标签;
无符号字符test2[2]={1,2};
无符号字符test3[3]={1,2,3};
无符号字符test4[4]={1,2,3,4};
listNew(&l,sizeof(TLV*),listFree,Print);
tag=allocatelv(2,sizeof(test2),test2);
如果(标记!=NULL){
listPushFront(&l,&tag);
}
tag=allocatelv(3,sizeof(test3),test3);
如果(标记!=NULL){
listPushFront(&l,&tag);
}
tag=allocatelv(4,sizeof(test4),test4);
如果(标记!=NULL){
listPushFront(&l,&tag);
}
列表打印(&l);
列表销毁(&l);
返回0;
}
main.c是创建指向结构TLV的指针列表的一个示例。您可以通过使用
c
的两个功能来实现通用链表,即void
指针和函数指针
后者(函数指针)对于构建链表并不重要,但是如果您想对链表的数据做一些有用的事情,例如打印,则它是至关重要的
下面是一个完整的工作示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
void *data;
struct node *next;
} node;
int lst_nodeAdd(
node **head,
node **tail,
const void *data,
size_t szData);
void lst_nodePrint(
node *head,
void(*print)(const void *));
void lst_nodeFree(node *head);
/* PRINTING FUNCTIONS */
void print_int(const void *a);
void print_string(const void *str);
int main(void)
{
const char *str[] = {
"0x0001",
"0x0002",
"0x0003",
};
// head & tail
node *head = NULL;
node *tail = NULL;
// List of strings
lst_nodeAdd(&head, &tail, str[0], strlen(str[0]) + 1);
lst_nodeAdd(&head, &tail, str[1], strlen(str[1]) + 1);
lst_nodeAdd(&head, &tail, str[2], strlen(str[2]) + 1);
lst_nodePrint(head, print_string);
lst_nodeFree(head);
head = NULL;
tail = NULL;
//....................................................
// List of ints
int int_array[] = {
0,
1,
2,
};
lst_nodeAdd(&head, &tail, &int_array[0], sizeof(int));
lst_nodeAdd(&head, &tail, &int_array[1], sizeof(int));
lst_nodeAdd(&head, &tail, &int_array[2], sizeof(int));
lst_nodePrint(head, print_int);
lst_nodeFree(head);
head = NULL;
tail = NULL;
system("PAUSE");
return 0;
}
int lst_nodeAdd(
node **head,
node **tail,
const void *data,
size_t szData)
{
void *tmp;
tmp = malloc(sizeof(node));
if (!tmp)
{
return 0;
}
((node *)tmp)->next = NULL;
((node *)tmp)->data = malloc(szData);
if (!((node *)tmp)->data)
{
free(tmp);
return 0;
}
memcpy(((node *)tmp)->data, data, szData);
if (!*head)
{
*head = (node *)tmp;
}
else
{
(*tail)->next = (node *)tmp;
}
*tail = (node *)tmp;
return 1;
}
void lst_nodePrint(
node *head,
void(*print)(const void *))
{
while (head)
{
print(head->data);
head = head->next;
}
}
void lst_nodeFree(node *head)
{
node *tmp = head;
while (head)
{
head = head->next;
free(tmp->data);
free(tmp);
tmp = head;
}
}
void print_int(const void *a)
{
printf("%d\n", *(const int *)a);
}
void print_string(const void *str)
{
puts((const char *)str);
}
#包括
#包括
#包括
类型定义结构节点{
作废*数据;
结构节点*下一步;
}节点;
int lst_nodead(
节点**头,
节点**尾部,
const void*数据,
大小(数据);
无效lst_节点打印(
节点*头,
无效(*打印)(常量无效*);
void lst_nodeFree(节点*头部);
/*打印功能*/
无效打印(const void*a);
无效打印字符串(const void*str);
内部主(空)
{
常量字符*str[]={
“0x0001”,
“0x0002”,
“0x0003”,
};
//头尾
node*head=NULL;
node*tail=NULL;
//字符串列表
第一个节点(&head,&tail,str[0],strlen(str[0])+1);
第一个节点(&head,&tail,str[1],strlen(str[1])+1);
第一个节点(&head,&tail,str[2],strlen(str[2])+1);
lst_nodePrint(打印头、打印字符串);
第一个诺德弗里(负责人);
head=NULL;
tail=NULL;
//....................................................
//INT列表
int_数组[]={
0,
1.
2.
};
lst_nodead(&head,&tail,&int_数组[0],sizeof(int));
第一个节点头(&head,&tail,&intar)