I am quite new to C and having a lot of trouble with generic linked lists in c.
Im trying to convert my linked list into a generic one but I don't really understand how to.
This is my original one:
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;
I understand that the data has to be a void
but can you have more than one void *data;
in a node.
So far I have this:
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;
But I don't know how I go about accessing and changing 3 lots of data in one void *data
.
CodePudding user response:
You can use macros:
#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";
}
It's somewhat ugly, but it works. Alternatively, if you can use a C compiler instead, you can use templates.
CodePudding user response:
C does not have typed generic aggregates such as C templates, but you can implement simpler aggregates pointing to data items via void *
pointers. You can also use macros to mix the data and the aggregation internals, but it requires more advanced C skills.
Here is an example using void *
for data:
#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;
}