我目前正在学习C,作为一个有更多高级语言经验的人。
在考虑了你的一些评论并做了一些测试和改进之后,我想出了一个更好的解决方案(向下滚动)。
但建议和评论仍然非常受欢迎。
那就是说,我在C中使用动态数组处理有点挣扎。我把它归结为一点,我非常喜欢,只需用NULL
终止每个数组并在必要时使用realloc
。
基本上我正在寻求建议:除了显而易见的(不能使用NULL值作为数据值)之外,是否存在任何缺点(请参见下面的示例代码)?
#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);
}
在阅读完答案并自己调试之后,我想出了一个新版本,主要基于下面提到的struct
方法。
看看,告诉我,我现在做错了什么。 :)
#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);
}
答案 0 :(得分:2)
你的array_length
是O(N)。如果在数组中添加大量项目,这将导致二次运行时间,这可能会非常慢。
你可以这样使用结构来存储数组的大小
struct dyn_array {
size_t array_size; // how many elements fit in the array?
size_t nelems; // how much array space are we using now?
int *elems; //or void*, you know the drill...
}
此方法的一个好处是您不再需要使用NULL终止符。它还允许您使用int(或其他任何)数组,而不仅仅是指针数组。
答案 1 :(得分:0)
这就是羊角面包的意思:
#define NULL 0 // in some include file.
这很不寻常,但可能。现在假设0是一个4字节的int,而void **数组是一个8字节的指针:
void* array_new(){
void** array = malloc(sizeof(NULL)); // this works
array[0] = NULL; // this write 8 bytes
return array;
}
array[0]=NULL
将0解释为8字节指针,并将其写入分配的4个字节以及更高的字节。