我对C很陌生,在C中使用通用链表有很多麻烦。
我想把我的链表转换成一个通用的,但我真的不知道怎么做。
这是我的原版:
typedef struct LLNode {
int rowPos;
int colPos
char Charecter
struct LLNode *next;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
} LinkedList;
我理解数据必须是一个void
,但是你可以在一个节点中有多个void *data;
吗?
到目前为止,我有这个:
typedef struct LLNode {
void *data;
struct LLNode *next;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
} LinkedList;
但是我不知道如何在一个void *data
中访问和更改3个数据。
可以使用宏:
#define LNODE(Type) LNode_ ## Type
#define LLIST(Type) LList_ ## Type
#define DECL_LINKED_LIST(Type)
typedef struct LNODE(Type) { Type value; struct LNODE(Type)* next; } LNODE(Type);
typedef struct LLIST(Type) { LNODE(Type)* head; LNODE(Type)* tail; } LLIST(Type);
typedef struct {
char const* f_name;
char const* l_name;
} Person;
DECL_LINKED_LIST(Person);
int main() {
LLIST(Person) list;
LNODE(Person) node1;
list.head = list.tail = &node1;
node1.next = 0;
node1.value.f_name = "John";
node1.value.l_name = "Smith";
}
它有点丑,但它有效。或者,如果你可以使用c++编译器,你可以使用模板。
C没有类型化的泛型聚合,比如c++模板,但是你可以通过void *
指针实现指向数据项的更简单的聚合。您也可以使用宏来混合数据和聚合内部,但这需要更高级的C技能。
下面是一个使用void *
的数据示例:
#include <stdio.h>
#include <stdlib.h>
/* generic list handling */
typedef struct LLNode {
struct LLNode *next;
void *data;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
} LinkedList[1];
void LinkedList_init(LinkedList list) {
if (list) {
list->head = list->tail = NULL;
}
}
void *LinkedList_append(LinkedList list, void *data) {
if (list) {
LLNode *node = malloc(sizeof(*node));
if (node != NULL) {
node->data = data;
node->next = NULL;
if (list->head == NULL) {
list->head = list->tail = node;
} else {
list->tail = list->tail->next = node;
}
return data;
}
}
return NULL;
}
void *LinkedList_delete(LinkedList list, void *data) {
if (list) {
for (LLNode **np = &list->head, *last = NULL; *np;) {
LLNode *node = *np;
if (node->data == data) {
if ((*np = node->next) == NULL)
list->tail = last;
free(node);
return data;
} else {
last = node;
np = &node->next;
}
}
}
return NULL;
}
void LinkedList_free(LinkedList list, int free_data) {
if (list) {
for (LLNode *node = list->head, *next; node; node = next) {
next = node->next;
if (free_data)
free(node->data);
free(node);
}
list->head = list->tail = NULL;
}
}
#define LinkedList_foreach(var, list)
for (LLNode *np__ = (list)->head, *next__; np__ != NULL; np__ = next__)
for (var = (next__ = np__->next, np__)->data; np__; np__ = NULL)
/* use a generic list for my data */
typedef struct MyData {
int rowPos;
int colPos;
char Character;
} MyData;
typedef struct MyList {
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
LinkedList list; // linked list of MyData items
} MyList;
MyList *MyList_alloc(void) {
MyList *lp = calloc(sizeof(*lp), 1);
LinkedList_init(lp->list);
return lp;
}
void MyList_free(MyList *lp) {
LinkedList_free(lp->list, 1);
free(lp);
}
MyData *MyList_add(MyList *lp, int row, int col, char c) {
MyData *dp = malloc(sizeof(*dp));
dp->rowPos = row;
dp->colPos = col;
dp->Character = c;
return LinkedList_append(lp->list, dp);
}
void MyList_delete(MyList *lp, MyData *dp) {
free(LinkedList_delete(lp->list, dp));
}
void MyList_print(MyList *lp) {
printf("{n");
LinkedList_foreach(MyData *dp, lp->list) {
printf(" { %d, %d, '%c' }n", dp->rowPos, dp->colPos, dp->Character);
}
printf("};n");
}
void MyList_filter_diagonal(MyList *lp) {
LinkedList_foreach(MyData *dp, lp->list) {
if (dp->rowPos == dp->colPos)
MyList_delete(lp, dp);
}
}
int main() {
MyList *mylist = MyList_alloc();
MyList_add(mylist, 0, 0, 'A');
MyData *d1 = MyList_add(mylist, 1, 2, 'B');
MyList_add(mylist, 2, 2, 'C');
MyList_add(mylist, 3, 5, 'D');
MyList_print(mylist);
MyList_delete(mylist, d1);
MyList_print(mylist);
MyList_filter_diagonal(mylist);
MyList_print(mylist);
MyList_free(mylist);
return 0;
}