zc_arraylist.h
/** * 实现类似列表的功能 * */ #ifndef __zc_arraylist_h #define __zc_arraylist_h #define ARRAY_LIST_DEFAULT_SIZE 32 //删除、比较两个函数类型声明 typedef void (*zc_arraylist_del_fn) (void *data); typedef int (*zc_arraylist_cmp_fn) (void *data1, void *data2); typedef struct{ void **array; //指针的指针 int len; int size; zc_arraylist_del_fn del; } zc_arraylist_t; zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del); void zc_arraylist_del(zc_arraylist_t *a_list); int zc_arraylist_set(zc_arraylist_t *a_list, int i, void *data); int zc_arraylist_add(zc_arraylist_t *a_list, void *data); int zc_arraylist_sortadd(zc_arraylist_t *a_list, zc_arraylist_cmp_fn cmp, void *data); #define zc_arraylist_len(a_list) (a_list->len) //i从0开始 #define zc_arraylist_get(a_list, i) ((i >= a_list->len) ? NULL : a_list->array[i]) //100 #define zc_arraylist_foreach(a_list, i, a_unit) for(i = 0, a_unit = a_list->array[0]; (i < a_list->len) && (a_unit = a_list->array[i], 1); i++) #endif
zc_arraylist.h
#include <stdlib.h> #include <string.h> #include <errno.h> #include "zc_defs.h" zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del){ zc_arraylist_t *a_list; a_list = (zc_arraylist_t *)calloc(1, sizeof(zc_arraylist_t)); if(!a_list){ zc_error("calloc fail, errno[%d]", errno); return NULL; } a_list->size = ARRAY_LIST_DEFAULT_SIZE; a_list->len = 0; a_list->del = del; //this could be null a_list->array = (void **)calloc(a_list->size, sizeof(void *)); if(!a_list->array){ zc_error("calloc fail, errno[%d]", errno); free(a_list); return NULL; } return a_list; } void zc_arraylist_del(zc_arraylist_t *a_list){ int i; if(!a_list){ return; } if(a_list->del){ for(i=0; i<a_list->len; i++){ //notice NULL if(a_list->array[i]){ a_list->del(a_list->array[i]); } } } if(a_list->array){ free(a_list->array); } free(a_list); return; } /** * static->function, external->internal */ static int zc_arraylist_expand_inner(zc_arraylist_t *a_list, int max){ void **tmp; int new_size; int diff_size; new_size = zc_max(a_list->size * 2, max); tmp = (void **)realloc(a_list->array, new_size * sizeof(void *)); if(!tmp){ zc_error("realloc fail, errno[%d]", errno); free(a_list->array); //notice no question? return -1; } a_list->array = tmp; diff_size = new_size - a_list->size; if(diff_size){ memset(a_list->array + a_list->size, 0x00, diff_size * sizeof(void *)); } a_list->size = new_size; return 0; } int zc_arraylist_set(zc_arraylist_t *a_list, int idx, void *data){ //idx start 0 if(idx > a_list->size - 1){ if(zc_arraylist_expand_inner(a_list, idx)){ zc_error("expand_internal fail"); return -1; } } if(a_list->array[idx] && a_list->del){ a_list->del(a_list->array[idx]); } a_list->array[idx] = data; if(a_list->len <= idx){ a_list->len = idx + 1; } return 0; } int zc_arraylist_add(zc_arraylist_t *a_list, void *data){ return zc_arraylist_set(a_list, a_list->len, data); } //assume idx < len static int zc_arraylist_insert_inner(zc_arraylist_t *a_list, int idx, void *data){ if(a_list->array[idx] == NULL){ a_list->array[idx] = data; return 0; } if(a_list->len + 1 > a_list->size){ if(zc_arraylist_expand_inner(a_list, 0)){ zc_error("expand_internal fail"); return -1; } } memmove(a_list->array + idx + 1, a_list->array + idx, (a_list->len - idx) * sizeof(void *)); a_list->array[idx] = data; a_list->len++; return 0; } int zc_arraylist_sortadd(zc_arraylist_t *a_list, zc_arraylist_cmp_fn cmp, void *data){ int i; for(i = 0; i < a_list->len; i++){ if((*cmp)(a_list->array[i], data) > 0){ break; } } if(i == a_list->len){ return zc_arraylist_add(a_list, data); }else{ //i < a_list->len return zc_arraylist_insert_inner(a_list, i, data); } }
用zc_arraylist实现一个字符串列表功能,测试zc_arraylist
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "zc_defs.h" char *char_new(char *p_str){ char *p = (char *)calloc(1, strlen(p_str) + 1); if(!p){ return NULL; } strncpy(p, p_str, strlen(p_str)); return p; } void char_del(void *p_str){ if(!p_str){ return; } free(p_str); } int main(){ zc_arraylist_t *char_list = zc_arraylist_new(char_del); zc_arraylist_add(char_list,char_new("www.baidu.com")); zc_arraylist_add(char_list,char_new("www.qq.com")); zc_arraylist_add(char_list,char_new("www.ifeng.com")); int i; char *char_item; zc_arraylist_foreach(char_list, i, char_item){ printf("%s ", char_item); } zc_arraylist_del(char_list); }
测试结果