1)字符串在结构体中
一个字符串做键的哈希(字符串在结构体中):uthash_exer1.c
#include <string.h> /* strcpy */
#include <stdlib.h> /* malloc */
#include <stdio.h> /* printf */
#include "uthash.h"
struct my_struct {
char name[10]; /* 键(字符串在这个结构体内部) */
int id;
UT_hash_handle hh; /* 使得这结构体可哈希 */
};
int main(int argc, char *argv[]) {
const char *names[] = { "joe", "bob", "betty", NULL };
struct my_struct *s, *tmp;
struct my_struct *users = NULL; //用作哈希表头
//分配一个结构体,内部name成员存储传入的字符串
//并且使用结构体name字段将结构体存入以s为表头的哈希表
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);
}
// 根据传入字符串为键,从哈希表中查找结构体,如果存在,输出这个结构体的id成员变量
for (int i = 0; names[i]; i++){
HASH_FIND_STR(users, names[i], s);
if (s) printf("%s's id is %d\n", names[i] ,s->id);
}
/* 从哈希表中取出结构体,并且从哈希表中删除,然后释放这个结构体 */
HASH_ITER(hh, users, s, tmp) {
HASH_DEL(users, s);
free(s);
}
return 0;
}
编译以上程序,进行测试:
[blctrl@rockygu uthash]$ gcc uthash_exer1.c -o uthash_exer1
[blctrl@rockygu uthash]$ ./uthash_exer1
joe's id is 0
bob's id is 1
betty's id is 2
2)在结构体中字符串指针
现在,这是一个相同示例,但使用了一个char *键替换char []。
一个以字符串为键的哈希(结构体中指字符指针)
#include <string.h> /* strcpy */
#include <stdlib.h> /* malloc */
#include <stdio.h> /* printf */
#include "uthash.h"
struct my_struct {
const char *name; /* 键:内容在结构体外 */
int id;
UT_hash_handle hh; /* 使得这个结构体可哈希 */
};
int main(int argc, char *argv[]) {
const char *names[] = { "joe", "bob", "betty", NULL };
struct my_struct *s, *tmp;
struct my_struct *users = NULL; //哈希表头
for (int i = 0; names[i]; ++i) {
s = (struct my_struct *)malloc(sizeof *s);
s->name = names[i]; //结构体的name成员指向一个字符串
s->id = i;
// 结构体可哈希标识成员,哈希表头,作为键的成员变量,成员变量指向字符串的长度,要放入哈希表的结构体
HASH_ADD_KEYPTR(hh, users, s->name, strlen(s->name), s);
}
for (int i = 0; names[i]; i++){
HASH_FIND_STR(users, names[i], s);
if (s) printf("%s's id is %d\n", names[i], s->id);
}
/* 释放哈希表,并且释放分配的结构体*/
HASH_ITER(hh, users, s, tmp) {
HASH_DEL(users, s);
free(s);
}
return 0;
}
编译以上程序,进行测试:
[blctrl@rockygu uthash]$ gcc uthash_exer2.c -o uthash_exer2
[blctrl@rockygu uthash]$ ./uthash_exer2
joe's id is 0
bob's id is 1
betty's id is 2
3) 指针键
键可以是一个指针。
#include <stdio.h>
#include <stdlib.h>
#include "uthash.h"
typedef struct {
void *key;
int i;
UT_hash_handle hh;
} el_t;
el_t *hash = NULL; //哈希表表头
char *someaddr = "Hello World found by uthash";
int main() {
el_t *d;
el_t *e = (el_t *)malloc(sizeof(el_t));
if (!e){
return -1;
}
printf("address:0x%p->%s", &someaddr, someaddr);
// 结构体成员变量key存储了一个地址
e->key = (void*)someaddr;
e->i = 1;
// 以结构体字段key为键,将结构体e存入哈希表hash
HASH_ADD_PTR(hash, key, e);
// 以变量someaddr的地址为键,在哈希表hash中查找结构体,用d指向找到的结构体
HASH_FIND_PTR(hash, &someaddr, d);
if (d) {
printf("found\n");
printf("content:%s\n", (char *)d->key);
}
/* 从哈希表中删除这个结构体 */
HASH_DEL(hash, e);
/* 释放这个结构体 */
free(e);
return 0;
}
编译测试以上程序:
[blctrl@rockygu uthash]$ gcc uthash_exer3.c -o uthash_exer3
[blctrl@rockygu uthash]$ ./uthash_exer3
address:0x0x602058->Hello World found by uthashfound
content:Hello World found by uthash
4) 结构体键
你的键字段可以有任何数据类型。对于uthash,它只是一个字节序列。因而,即使一个嵌套结构体也可以被用作一个键。我们将使用一般宏HASH_ADD和HASH_FIND来演示。
在添加一个项到这个哈希或者查找一个项前,这些填充字节必须被置零。因而,在设置感兴趣成员前,总是置零整个结构体。以下示例做了这件事,键对memset的两次调用。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "uthash.h"
typedef struct {
char a;
int b;
} record_key_t;
typedef struct {
record_key_t key; // 作为这个结构体的键
int i;
char name[21];
UT_hash_handle hh;
} record_t;
int main(int argc, char *argv[]) {
record_key_t l;
record_t *p, *r, *tmp;
record_t *records = NULL; // 作为哈希表头
r = (record_t *)malloc(sizeof(record_t));
// 对分配的record_t结构体填充0
memset(r, 0, sizeof(record_t));
// 设置键
r->key.a = 'a';
r->key.b = 1;
// 设置其它成员
r->i = 666;
strcpy(r->name, "hello world, uthash");
// 用结构体的key字段作为键,并出入这个键的尺寸,将结构体r放入哈希表records
HASH_ADD(hh, records, key, sizeof(record_key_t), r);
// 对record_key_t类型的变量填充0
memset(&l, 0, sizeof(record_t));
// 设置键
l.a = 'a';
l.b = 1;
// 通过类型record_key_t的键,并且传入这个键的大小,查找结构体,并且用p指向这个结构体
HASH_FIND(hh, records, &l, sizeof(record_key_t), p);
if (p) {
printf("found %c %d\n", p->key.a, p->key.b);
printf("content:%d, %s\n", p->i, p->name);
}
HASH_ITER(hh, records, p, tmp) {
HASH_DEL(records, p);
free(p);
}
return 0;
}
编译以上程序,并进行测试:
[blctrl@rockygu uthash]$ gcc uthash_exer4.c -o uthash_exer4
[blctrl@rockygu uthash]$ ./uthash_exer4
found a 1
content:666, hello world, uthash