I am currently learning C, as someone, who has quite a bit of experience in more high-level languages than that.
After considering some of your comments and doing a bit more testing and fidelling, I came up with a better solution (scroll down).
Advice and comments are still very welcome though.
That said, I struggle a bit with dynamic array handling in C. I got it down to a point, where I quite like, simply terminating every array with NULL
and using realloc
where neccessary.
Basically I am in search of advice: Is there any downside, of doing it that way (see example code below), besides the obvious (can't use NULL values as data value) ?
#include "stdlib.h"
int array_length(void* array)
{
int i;
for (i = 0; ((void**)array)[i]; i++);
return i;
}
void array_add(void* array, void* item)
{
int size = array_length(array);
realloc(array, sizeof(item) * (size + 2));
((void**)array)[size] = item;
((void**)array)[size + 1] = NULL;
}
void* array_new(){
void** array = malloc(sizeof(NULL));
array[0] = NULL;
return array;
}
#include "stdio.h"
void print_items(char** array){
printf("%i - [", array_length(array));
for (int i = 0; array[i]; i++){
printf("\"%s\"", array[i]);
if (array[i+1])
printf(", ");
}
printf("]\n");
}
int main(){
char** str_list = array_new();
print_items(str_list);
array_add(str_list, "Something!");
print_items(str_list);
array_add(str_list, "Another Thing.");
print_items(str_list);
}
Better Version (Update!)
After reading through your answers and debugging a bit more myself, I came up with a new version, which is mainly based on the struct
approach mentioned below.
Have a Look, and tell me, what I am doing wrong now. :)
#include "stdlib.h"
#include "assert.h"
typedef void* Any;
typedef struct {
Any* items;
int count;
} List;
List* list_new(){
List* list = malloc(sizeof(List));
list->items = NULL;
list->count = 0;
return list;
}
void list_add(List* list, Any element){
int count = list->count + 1;
list->items = realloc(list->items, count * sizeof(element));
list->items[count-1] = element;
list->count = count;
}
void list_free(List* list){
if (list){
if (list->items) free(list->items);
free(list);
}
}
void list_each(List* list, void (*callback)(List*, Any, int)){
for (int i = 0; i < list->count; i++){
callback(list, list->items[i], i);
}
}
// Sample usage
#include "stdio.h"
void debug_item(List* list, Any item, int index){
if(index > 0) printf(", ");
printf("\"%s\"", item);
}
void debug(List* list){
printf("%i : [", list->count);
list_each(list, debug_item);
printf("]\n");
}
int main(){
List* cats = list_new();
debug(cats);
list_add(cats, "Baltazar");
list_add(cats, "Scar");
list_add(cats, "Garfield");
debug(cats);
list_free(cats);
}