日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uthash简介

發布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uthash简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • C語言hash總結
    • 一、 uthash的使用
      • Key類型為int時
      • 使用注意事項總結
    • 二、 完整的例子
      • 2.1 key為int
      • 2.2 key為字符數組
      • 2.3 key為字符

C語言hash總結

本文內容基本來自對官網的翻譯,若有不準確的地方,望指正。
?uthash 是C的比較優秀的開源代碼,已經集成到最新的GCC。它實現了常見的hash操作函數,例如查找、插入、刪除等待。該套開源代碼采用宏的方式實現hash函數的相關功能,支持C語言的任意數據結構最為key值,甚至可以采用多個值作為key,無論是自定義的struct還是基本數據類型,需要注意的是不同類型的key其操作接口方式略有不同。使用uthash代碼時只需要包含頭文件"uthash.h"即可。由于該代碼采用宏的方式實現,所有的實現代碼都在uthash.h文件中,因此只需要在自己的代碼中包含該頭文件即可。

一、 uthash的使用

? 首先,需要定義一個結構體:

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

其中,

  • id是鍵(key),也可以是其他的數據結構,不同的數據結構對應hash操作可能不一樣

  • name是值(value),其類型根據實際情況定義

  • hh是內部使用的hash處理句柄,在使用過程中,只需要在結構體中定義一個UT_hash_handle類型的變量即可,不需要為該句柄變量賦值,但必須在該結構體中定義該變量

    然后,你只需要愉快的調用uthash所定義的api就可以愉快的使用hash啦。然我們舉個例子吧。

    Key類型為int時

  • 定義一個key為int類型的hash結構體
struct MyStruct {int key; /* key */char value[10]; /* value, 若無value也可以去掉該變量 */UT_hash_handle hh; }; struct MyStruct *g_users = NULL;
  • 注意:定義一個hash結構的空指針g_users,用于指向保存數據的hash表,必須初始化為空,在后面的查、插等操作中,uthash內部會根據其是否為空而進行不同的操作。
    2. 封裝自己的查找接口
void AddUser(int iKey, char *iValue) {struct MyStruct *s;HASH_FIND_INT(g_users, &iKey, is); /* 插入前先查看key值是否已經在hash表g_users里面了 */if (s==NULL) {s = (struct MyStruct *)malloc(sizeof(struct MyStruct));s->key = iKey;HASH_ADD_INT(g_users, key, s); /* 第二個參數為hash結構里面,hash key值的變量名 */}strcpy(s->value, iValue); }

? 由于uthash要求鍵(key)必須唯一,而uthash內部未對key值得唯一性進行很好的處理,因此它要求外部在插入操作時要確保其key值不在當前的hash表中。若插入相同的key值到一個hash中,會被當做一種錯誤。

? 3. 封裝實現刪除接口

void DeleteUser(int ikey) {struct MyStruct *s = NULL;HASH_FIND_INT(g_users, &ikey, s);if (s==NULL) {HASH_DEL(g_users, s); // HASH_DEL 只將結構體從hash表中移除,并未釋放結構體內容free(s); } }

? 4. 統計hash表中的元素個數

unsigned int numUsers; numUsers = HASH_COUNT(g_users); printf("there are %u items\n", numUsers);

? 5. 遍歷元素

struct MyStruct *s, *tmp; HASH_ITER(hh, g_users, s, tmp) {printf("user ikey %d: value %s\n", s->key, s->value);/* ... it is safe to delete and free s here */ }

? 還有另外一種刪除方法(更加推薦前一種,不易出錯)

struct MyStruct *s; for(s = g_users; s != NULL; s = s->hh.next) {printf("user ikey %d: value %s\n", s->key, s->value); }

? 6. 清空hash表

void DeleteHash() {struct MyStruct *currentUser, *tmp;HASH_ITER(hh, g_users, currentUser, tmp) {HASH_DEL(g_users, currentUser); free(currentUser); } }

使用注意事項總結

  • 在定義hash結構體時不要忘記定義UT_hash_handle的變量

  • 需確保key值唯一,如果插入key-value對時,key值已經存在,再插入的時候就會出錯

  • 不同的key值,其增加和查找調用的接口函數不一樣。一般情況下,不通類型的key,其插入和查找接口函數是不一樣的,刪除、遍歷、元素統計接口是通用的,特殊情況下,字符數組和字符串作為key值時,其插入接口函數不一樣,但是查找接口是一樣的

  • 以上舉的例子中,g_users是全局變量。但是如果函數如AddUser想將hash結構體的指針g_users作為參數傳入。則有以下問題

    /* bad */ void AddUser(struct Mytruct *users, int key, char *name) {...HASH_ADD_INT(users, key, s); } /* good */ void AddUser(struct Mytruct **users, int key, char *name) { ...HASH_ADD_INT( *users, key, s ); }

    官方給出的解釋如下:The reason it’s necessary to deal with a pointer to the hash pointer is simple: the hash macros modify it (in other words, they modify the pointer itself not just what it points to). 就是這個指針的值會變化。

二、 完整的例子

2.1 key為int

#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); }void delete_all() {struct my_struct *current_user, *tmp;HASH_ITER(hh, users, current_user, tmp) {HASH_DEL(users, current_user); /* delete it (users advances to next) */free(current_user); /* free it */} }void print_users() {struct my_struct *s;for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {printf("user id %d: name %s\n", s->id, s->name);} }int name_sort(struct my_struct *a, struct my_struct *b) {return strcmp(a->name,b->name); }int id_sort(struct my_struct *a, struct my_struct *b) {return (a->id - b->id); }void sort_by_name() {HASH_SORT(users, name_sort); }void sort_by_id() {HASH_SORT(users, id_sort); }int main(int argc, char *argv[]) {char in[10];int id=1, running=1;struct my_struct *s;unsigned num_users;while (running) {printf(" 1. add user\n");printf(" 2. add/rename user by id\n");printf(" 3. find user\n");printf(" 4. delete user\n");printf(" 5. delete all users\n");printf(" 6. sort items by name\n");printf(" 7. sort items by id\n");printf(" 8. print users\n");printf(" 9. count users\n");printf("10. quit\n");gets(in);switch(atoi(in)) {case 1:printf("name?\n");add_user(id++, gets(in));break;case 2:printf("id?\n");gets(in); id = atoi(in);printf("name?\n");add_user(id, gets(in));break;case 3:printf("id?\n");s = find_user(atoi(gets(in)));printf("user: %s\n", s ? s->name : "unknown");break;case 4:printf("id?\n");s = find_user(atoi(gets(in)));if (s) delete_user(s);else printf("id unknown\n");break;case 5:delete_all();break;case 6:sort_by_name();break;case 7:sort_by_id();break;case 8:print_users();break;case 9:num_users=HASH_COUNT(users);printf("there are %u users\n", num_users);break;case 10:running=0;break;}}delete_all(); /* free any structures */return 0; }

2.2 key為字符數組

#include <string.h> /* strcpy */ #include <stdlib.h> /* malloc */ #include <stdio.h> /* printf */ #include "uthash.h"struct my_struct {char name[10]; /* key (string is WITHIN the structure) */int id;UT_hash_handle hh; /* makes this structure hashable */ };int main(int argc, char *argv[]) {const char *names[] = { "joe", "bob", "betty", NULL };struct my_struct *s, *tmp, *users = NULL;for (int i = 0; names[i]; ++i) {s = (struct my_struct *)malloc(sizeof *s);strcpy(s->name, names[i]);s->id = i;HASH_ADD_STR(users, name, s);}HASH_FIND_STR( users, "betty", s);if (s) printf("betty's id is %d\n", s->id);/* free the hash table contents */HASH_ITER(hh, users, s, tmp) {HASH_DEL(users, s);free(s);}return 0; }

2.3 key為字符

#include <string.h> /* strcpy */ #include <stdlib.h> /* malloc */ #include <stdio.h> /* printf */ #include "uthash.h"struct my_struct {const char *name; /* key */int id;UT_hash_handle hh; /* makes this structure hashable */ };int main(int argc, char *argv[]) {const char **n, *names[] = { "joe", "bob", "betty", NULL };struct my_struct *s, *tmp, *users = NULL;int i=0;for (n = names; *n != NULL; n++) {s = (struct my_struct*)malloc(sizeof(struct my_struct));s->name = *n;s->id = i++;HASH_ADD_KEYPTR(hh, users, s->name, strlen(s->name), s);}HASH_FIND_STR(users, "betty", s);if (s) printf("betty's id is %d\n", s->id);/* free the hash table contents */HASH_ITER(hh, users, s, tmp) {HASH_DEL(users, s);free(s);}return 0; }

參考鏈接:

https://github.com/troydhanson/uthash
http://troydhanson.github.io/uthash/
http://troydhanson.github.io/uthash/userguide.html

?

總結

以上是生活随笔為你收集整理的uthash简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。