哈希表C开源的uthash的简单初步封装(二)

来源:互联网 发布:linux dhcp服务配置 编辑:程序博客网 时间:2024/06/02 05:12

概述:在上一篇博客中,简单封装了key为int类型的哈希表的增删,遍历等函数,但是在上一篇封装中,函数均是可见的,可能并不安全,所以这一次就将函数封装到结构体,像使用c++一样,直接通过结构体就可以运行函数。所有函数操作都是静态的,这样操作更加方便快捷。此次封装了key为int, char[],char * , void *四种类型的哈希表结构。在多线程中,依旧是不安全的,后期有时间会加入互斥锁,读写锁到里面,用于多线程。

1,这里就说一下key类型为char []的封装,先看.h文件,先封装一个hash的结构体,再定义一个hash控制结构体,将操作函数放在hash控制结构体,同时将hash的结构体也放入hash控制结构体。

#ifndef _SKY_HASH_H_#define _SKY_HASH_H_#include <stdlib.h>#include "uthash.h"#define KEY_ARR_SIZE      16typedef struct hash_arr hash_arr_t;typedef void (*hash_arr_cb_t)(hash_arr_t *, void *);/*key 为char[]类型结构体封装*/typedef hash_arr_t *(*hash_arr_find_t)(hash_arr_t **, char *);typedef int (*hash_arr_add_t)(hash_arr_t **, char *, void *);typedef int (*hash_arr_del_t)(hash_arr_t **, char *);typedef void (*hash_arr_delall_t)(hash_arr_t **);typedef int (*hash_arr_count_t)(hash_arr_t **);typedef void (*hash_arr_ergodic_t)(hash_arr_t **, hash_arr_cb_t, void *);typedef struct hash_arr_ctl hash_arr_ctl_t;struct hash_arr {      char key[KEY_ARR_SIZE];    /* key */      void *data;                /*数据*/    UT_hash_handle hh;         /* makes this structure hashable */  };struct hash_arr_ctl {    hash_arr_t *hash;    hash_arr_find_t find;    hash_arr_add_t add;    hash_arr_del_t del;    hash_arr_delall_t delall;    hash_arr_count_t count;    hash_arr_ergodic_t ergodic;};/*char []类型key相关操作函数*/void hash_arr_create(hash_arr_ctl_t *ha);

2,我们再看一下sky_hash.c文件,这个就没啥了,主要就是uthash的函数使用及简单封装,看uthash操作手册就可以看懂了。

#include <stdio.h>#include <stdlib.h>#include "uthash.h"#include "sky_hash.h"/*****************************************************************************                    下方封装key为char []类型的增删,遍历等操作。                                                            By Sky(Peace&Love)******************************************************************************//*查找键值*/hash_arr_t *hash_arr_find(hash_arr_t **hashlist, char key[]){    hash_arr_t *hd = NULL;    HASH_FIND_STR(*hashlist,key,hd);    return hd;}/*添加键值对*/int hash_arr_add(hash_arr_t **hashlist, char key[], void *data){    hash_arr_t *hd = hash_arr_find(hashlist,key);    if (NULL == hd) {        hd = (hash_arr_t *)malloc(sizeof(hash_arr_t));        strncpy(hd->key,key,KEY_ARR_SIZE);        hd->data = data;        HASH_ADD_STR(*hashlist,key,hd);    } else {        return -1;    }    return 0;}/*删除指定键值对*/static int hash_arr_del(hash_arr_t **hashlist, char key[]){    hash_arr_t *hd = hash_arr_find(hashlist,key);    if (NULL == hd) {        return -1;    }    HASH_DEL(*hashlist, hd);    if (NULL != hd->data) {        free(hd->data);        hd->data = NULL;    }    free(hd);    hd = NULL;    return 0;}/*删除所有键值对*/static void hash_arr_delall(hash_arr_t **hashlist){    hash_arr_t *hd,*tmp;    HASH_ITER(hh, *hashlist, hd, tmp) {        HASH_DEL(*hashlist, hd);          if (NULL != hd->data) {            free(hd->data);            hd->data = NULL;        }        free(hd);        hd = NULL;    }    if (NULL != *hashlist) {        free(*hashlist);        *hashlist = NULL;    }}/*遍历哈希表*/static void hash_arr_ergodic(hash_arr_t **hashlist, hash_arr_cb_t callback, void *arg){    hash_arr_t *hd,*tmp;    HASH_ITER(hh, *hashlist, hd, tmp) {        callback(hd,arg);    }}/*获取哈希表项目个数*/static int hash_arr_count(hash_arr_t **hashlist){    return HASH_COUNT(*hashlist);}/*key为char []类型的哈希表创建初始化*/void hash_arr_create(hash_arr_ctl_t *ha){    ha->hash = NULL;    ha->find = hash_arr_find;    ha->add = hash_arr_add;    ha->del = hash_arr_del;    ha->delall = hash_arr_delall;    ha->count = hash_arr_count;    ha->ergodic = hash_arr_ergodic;}

3,我们做一个测试程序,验证封装函数的正确性。

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include "./hash/sky_hash.h"typedef struct sky sky_t;/*只做测试使用,可以自定义*/struct sky {    int num;    /*用户可以自己再增加字段*/};void callback_keyarr(hash_arr_t *hd, void *arg){    sky_t *value = hd->data;    printf("key:%s,num:%d\n",hd->key,value->num);}void test_keyarr(){    hash_arr_ctl_t *ha = (hash_arr_ctl_t *)malloc(sizeof(hash_arr_ctl_t));    hash_arr_create(ha);    char *key[] = {"bboy","born","sky","peace","love"};    int i;    /*哈希表中添加数据*/    for (i = 0 ; i < 5 ; i ++) {        sky_t *value = (sky_t *)malloc(sizeof(sky_t));        value->num = i;        if (0 != ha->add(&ha->hash,key[i],value)) {            printf("hash add failed\n");            free(value);        }    }    printf("ha:%p\n",ha->hash);    /*遍历哈希表*/    ha->ergodic(&ha->hash,callback_keyarr,NULL);    /*获取哈希表项目个数*/    int count = ha->count(&ha->hash);    printf("hash count:%d\n",count);    /*查找哈希表*/    char fkey[16] = {0};    char *bb = "born";    memcpy(fkey,bb,5);    hash_arr_t *node = ha->find(&ha->hash,fkey);    if (NULL != node) {        sky_t *value = node->data;        printf("find key[born] value num = %d\n",value->num);        /*修改key对应的数据值*/        value->num = 100;    } else {        printf("not found\n");    }    /*删除指定项目*/    ha->del(&ha->hash,"bboy");    /*遍历哈希表*/    ha->ergodic(&ha->hash,callback_keyarr,NULL);    /*删除整个哈希表*/    ha->delall(&ha->hash);    printf("ha:%p\n",ha->hash);    free(ha);}int main(){    test_keyarr();    return 0;}

4,运行结果如下:
这里写图片描述

5,所有代码传到码云,develop分支。需要的话可以看下。地址在上一篇有。

原创粉丝点击