C语言uthash介绍

时间:2021-08-07
本文章向大家介绍C语言uthash介绍,主要包括C语言uthash介绍使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

介绍

uthash是C语言比较优秀的开源代码。它实现了常见的hash操作函数,例如插入、查找、删除等。该套开源代码采用宏的方式实现hash函数的相关功能,支持C语言的任意数据结构最为key值,甚至可以采用多个值作为key,无论是自定义的struct还是基本数据类型,需要注意的是不同类型的key其操作接口方式略有不同。由于该代码采用宏的方式实现,所有的实现代码都在uthash.h文件中,因此只需要在自己的代码中包含"uthash.h"头文件即可。

uthash最初是Troy D. Hanson的个人使用方便的目标,放到了SourceForge,后来因为受欢迎下载量比较大,就放到了GitHub吧。

uthash是遵从BSD开源协议,可供个人、商业和组织自由使用。

hash操作

官方文档详细介绍了uthash的使用。这里提炼一些基本信息
https://troydhanson.github.io/uthash/userguide.html

定义hash结构体

在你定义的hash结构体中嵌入UT_hash_handle。在哈希表中是通过指针操作的,不会进行移动和复制,因此不必担心速度和内存问题。

#include "uthash.h"

struct my_struct {
    int id;                    /* key */
    char name[10];
    UT_hash_handle hh;         /* makes this structure hashable */
};

key的类型

uthash支持任意类型的key,包括整型、字符串、指针、结构体等。如果key类型不同,那么add和find函数有不同的接口,但是HASH_DELETE和HASH_SORT不区分key类型。

hash操作接口

macro arguments
HASH_ADD_INT (head, keyfield_name, item_ptr)
HASH_REPLACE_INT (head, keyfield_name, item_ptr, replaced_item_ptr)
HASH_FIND_INT (head, key_ptr, item_ptr)
HASH_ADD_STR (head, keyfield_name, item_ptr)
HASH_REPLACE_STR (head, keyfield_name, item_ptr, replaced_item_ptr)
HASH_FIND_STR (head, key_ptr, item_ptr)
HASH_ADD_PTR (head, keyfield_name, item_ptr)
HASH_REPLACE_PTR (head, keyfield_name, item_ptr, replaced_item_ptr)
HASH_FIND_PTR (head, key_ptr, item_ptr)
HASH_DEL (head, item_ptr)
HASH_SORT (head, cmp)
HASH_COUNT (head)

举例

#include <stdio.h>   /* gets */
#include <stdlib.h>  /* atoi, malloc */
#include <string.h>  /* strcpy */
#include "uthash.h"

struct my_struct {
    int id;                    /* key */
    char name[10];
    UT_hash_handle hh;         /* makes this structure hashable */
};

struct my_struct *users = NULL;

void add_user(int user_id, char *name) {
    struct my_struct *s;

    HASH_FIND_INT(users, &user_id, s);  /* id already in the hash? */
    if (s == NULL) {
      s = (struct my_struct *)malloc(sizeof *s);
      s->id = user_id;
      HASH_ADD_INT(users, id, s);  /* id: name of key field */
    }
    strcpy(s->name, name);
}

struct my_struct *find_user(int user_id) {
    struct my_struct *s;

    HASH_FIND_INT(users, &user_id, s);  /* s: output pointer */
    return s;
}

void delete_user(struct my_struct *user) {
    HASH_DEL(users, user);  /* user: pointer to deletee */
    free(user);
}

list操作

utlist提供了链表的操作,支持三种链表:单链表、双链表、循环双链表。
官方文档详细介绍了utlist的使用。在源码中包含utlist.h头文件即可。
https://troydhanson.github.io/uthash/utlist.html

定义list结构体

在你定义的list中嵌入next、prev指针,就可实现单链表或者双链表。

typedef struct element {
    char *name;
    struct element *prev; /* needed for a doubly-linked list only */
    struct element *next; /* needed for singly- or doubly-linked lists */
} element;

list操作接口

支持list的头插法和尾插法的插入接口、查询接口、删除接口、遍历、排序等。

Prepend意味着在现有的列表头(如果有的话)前面插入一个元素,将列表头更改为新元素。Append意味着在列表的末尾添加一个元素,因此它成为新的尾元素。Concatenate接受两个正确构造的列表,并将第二个列表附加到第一个列表。要在任意元素(而不是列表头)之前添加前缀,请使用prepend ELEM宏族。要在任意元素元素之后添加元素而不是列表头,请使用append ELEM宏族。

Singly-linked Doubly-linked Circular, doubly-linked
LL_PREPEND(head,add); DL_PREPEND(head,add); CDL_PREPEND(head,add);
LL_PREPEND_ELEM(head,ref,add); DL_PREPEND_ELEM(head,ref,add); CDL_PREPEND_ELEM(head,ref,add);
LL_APPEND_ELEM(head,ref,add); DL_APPEND_ELEM(head,ref,add); CDL_APPEND_ELEM(head,ref,add);
LL_REPLACE_ELEM(head,del,add); DL_REPLACE_ELEM(head,del,add); CDL_REPLACE_ELEM(head,del,add);
LL_APPEND(head,add); DL_APPEND(head,add); CDL_APPEND(head,add);
LL_INSERT_INORDER(head,add,cmp); DL_INSERT_INORDER(head,add,cmp); CDL_INSERT_INORDER(head,add,cmp);
LL_CONCAT(head1,head2); DL_CONCAT(head1,head2); ``
LL_DELETE(head,del); DL_DELETE(head,del); CDL_DELETE(head,del);
LL_SORT(head,cmp); DL_SORT(head,cmp); CDL_SORT(head,cmp);
LL_FOREACH(head,elt) {…} DL_FOREACH(head,elt) {…} CDL_FOREACH(head,elt) {…}
LL_FOREACH_SAFE(head,elt,tmp) {…} DL_FOREACH_SAFE(head,elt,tmp) {…} CDL_FOREACH_SAFE(head,elt,tmp1,tmp2) {…}
LL_SEARCH_SCALAR(head,elt,mbr,val); DL_SEARCH_SCALAR(head,elt,mbr,val); CDL_SEARCH_SCALAR(head,elt,mbr,val);
LL_SEARCH(head,elt,like,cmp); DL_SEARCH(head,elt,like,cmp); CDL_SEARCH(head,elt,like,cmp);
LL_LOWER_BOUND(head,elt,like,cmp); DL_LOWER_BOUND(head,elt,like,cmp); CDL_LOWER_BOUND(head,elt,like,cmp);
LL_COUNT(head,elt,count); DL_COUNT(head,elt,count); CDL_COUNT(head,elt,count);

array操作

utarray实现了动态数组的功能。可存储整型数组和字符串,也可自定义其他类型。
https://troydhanson.github.io/uthash/utarray.html

utarray操作接口

macro description
utarray_new(UT_array *a, UT_icd *icd) allocate a new array
utarray_free(UT_array *a) free an allocated array
utarray_push_back(UT_array *a,void *p) push element p onto a
utarray_pop_back(UT_array *a) pop last element from a
utarray_len(UT_array *a) get length of a
utarray_insert(UT_array *a,void *p, int j) insert element p to index j
utarray_inserta(UT_array *a,UT_array *w, int j) insert array w into array a at index j
utarray_concat(UT_array *dst,UT_array *src) copy src to end of dst array
utarray_clear(UT_array *a) clear all elements from a, setting its length to zero
utarray_sort(UT_array *a,cmpfcn *cmp) sort elements of a using comparison function
utarray_find(UT_array *a,void *v, cmpfcn *cmp) find element v in utarray (must be sorted)
utarray_front(UT_array *a) get first element of a
utarray_next(UT_array *a,void *e) get element of a following e (front if e is NULL)
utarray_prev(UT_array *a,void *e) get element of a before e (back if e is NULL)
utarray_back(UT_array *a) get last element of a

举例

#include <stdio.h>
#include "utarray.h"

int main() {
  UT_array *nums;
  int i, *p;

  utarray_new(nums,&ut_int_icd);
  for(i=0; i < 10; i++) utarray_push_back(nums,&i);

  for(p=(int*)utarray_front(nums);
      p!=NULL;
      p=(int*)utarray_next(nums,p)) {
    printf("%d\n",*p);
  }

  utarray_free(nums);

  return 0;
}

string操作

utstring实现了动态字符串的功能。https://github.com/troydhanson/uthash

utstring操作接口

utstring_new(s) allocate a new utstring
utstring_renew(s) allocate a new utstring (if s is NULL) otherwise clears it
utstring_free(s) free an allocated utstring
utstring_init(s) init a utstring (non-alloc)
utstring_done(s) dispose of a utstring (non-alloc)
utstring_printf(s,fmt,…) printf into a utstring (appends)
utstring_bincpy(s,bin,len) insert binary data of length len (appends)
utstring_concat(dst,src) concatenate src utstring to end of dst utstring
utstring_clear(s) clear the content of s (setting its length to 0)
utstring_len(s) obtain the length of s as an unsigned integer
utstring_body(s) get char* to body of s (buffer is always null-terminated)
utstring_find(s,pos,str,len) forward search from pos for a substring
utstring_findR(s,pos,str,len) reverse search from pos for a substring

举例

#include <stdio.h>
#include "utstring.h"

int main() {
    UT_string *s;

    utstring_new(s);
    utstring_printf(s, "hello world!" );
    printf("%s\n", utstring_body(s));

    utstring_free(s);
    return 0;
}

原文地址:https://www.cnblogs.com/lvzh/p/15111775.html