I have the following code:
typedef struct ll_node linked_list_node;
struct ll_node {
int value;
linked_list_node* next;
};
typedef struct ll linked_list;
struct ll {
size_t size;
linked_list_node* head;
linked_list_node* tail;
};
void for_each(linked_list* list, void (*function)(linked_list_node*, ...)) {
if (list == NULL || list->head == NULL) {
return;
}
for (linked_list_node* node = list->head; node != NULL; node = node->next) {
function(node, function->__va_arg_pack());
}
}
What I mainly want to achieve is for_each
to receive a function that is executed to every single linked list node, but I'm not sure if that can be achieved with functions that receive multiple parameters... Please help!
CodePudding user response:
I didn't explain myself very well. I'm building a linked list library for C (just as a hobby), and I want that library to have a for_each function that mainly executes something (another function) to every single nodes in the linked list
Just let user pass an additional void *
argument. See for example at fopencookie
or pthread_create
or thrd_create
.
int for_each(linked_list* list, int (*function)(linked_list_node *, void *cookie), void *cookie) {
FOREACH_YOUR_LIST(i, list) {
int ret = function(i, cookie);
if (ret) {
// let users do early return
return ret;
}
}
return 0;
}
CodePudding user response:
If you are under gcc
you can achieve that using statement expressions and nested functions, here an example of somtehing similar to a lambda.
In plain c is much more difficult and you would have to deal with NULL-terminated va_args lists and a lot of black magic. Another option is to use the preprocessor, also with its disadvantages, but at least the implementation is easier:
#define FOR_EACH(list, function, ...) \
do { \
if (list == NULL || list->head == NULL) { \
break; \
} \
for (linked_list_node* node = list->head; node != NULL; node = node->next) { \
function(node, __VA_ARGS__); \
} \
} while (0)
void print(linked_list_node *node, int *count)
{
printf("%d) %d\n", (*count) , node->value);
}
void concat(linked_list_node *node, const char *str1, const char *str2)
{
printf("%s %d %s\n", str1, node->value, str2);
}
int main(void)
{
linked_list_node nodes[] = {{1, &nodes[1]} , {2, &nodes[2]}, {3, NULL}};
linked_list *list = &(linked_list){3, &nodes[0], &nodes[2]};
int count = 0;
FOR_EACH(list, print, &count);
FOR_EACH(list, concat, "Hi", "by");
return 0;
}
Output:
0) 1
1) 2
2) 3
Hi 1 by
Hi 2 by
Hi 3 by