⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 userguide.txt

📁 uthash 是一个C语言的哈希表
💻 TXT
📖 第 1 页 / 共 3 页
字号:
    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;   while(users) {     current_user = users;          /* grab pointer to first item */    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=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);}----------------------------------------------------------------------.A complete program (part 2 of 2)----------------------------------------------------------------------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;    struct my_struct *s;    unsigned num_users;    while (1) {        printf("1. add user\n");        printf("2. find user\n");        printf("3. delete user\n");        printf("4. delete all users\n");        printf("5. sort items by name\n");        printf("6. sort items by id\n");        printf("7. print users\n");        printf("8. count users\n");        gets(in);        switch(atoi(in)) {            case 1:                printf("name?\n");                add_user(id++, gets(in));                break;            case 2:                printf("id?\n");                s = find_user(atoi(gets(in)));                printf("user: %s\n", s ? s->name : "unknown");                break;            case 3:                printf("id?\n");                s = find_user(atoi(gets(in)));                if (s) delete_user(s);                else printf("id unknown\n");                break;            case 4:                delete_all();                break;            case 5:                sort_by_name();                break;            case 6:                sort_by_id();                break;            case 7:                print_users();                break;            case 8:                num_users=HASH_COUNT(users);                printf("there are %u users\n", num_users);                break;        }    }}----------------------------------------------------------------------This program is included in the distribution in `tests/example.c`. You can run`make example` in that directory to compile it easily.Kinds of keys-------------Integer keys~~~~~~~~~~~~The preceding examples demonstrated use of integer keys. To recap, use theconvenience macros `HASH_ADD_INT` and `HASH_FIND_INT` for structures withinteger keys. (The other operations such as `HASH_DELETE` and `HASH_SORT` arethe same for all types of keys).String keys~~~~~~~~~~~String keys are handled almost the same as integer keys. The convenience macrosfor dealing with string keys are called `HASH_ADD_STR` and `HASH_FIND_STR`.[NOTE].char[ ] vs. char* ================================================================================The string is 'within' the structure in the next example-- `name` is a`char[10]` field.  If instead our structure merely 'pointed' to the key (i.e.,`name` was declared `char *`), we'd use `HASH_ADD_KEYPTR`, described in<<Appendix_F,Appendix F>>.================================================================================.A string-keyed hash----------------------------------------------------------------------#include <string.h>  /* strcpy */#include <stdlib.h>  /* malloc */#include <stdio.h>   /* printf */#include "uthash.h"struct my_struct {    char name[10];             /* key */    int id;                        UT_hash_handle hh;         /* makes this structure hashable */};int main(int argc, char *argv[]) {    char **n, *names[] = { "joe", "bob", "betty", NULL };    struct my_struct *s, *users = NULL;    int i=0;    for (n = names; *n != NULL; n++) {        s = malloc(sizeof(struct my_struct));        strcpy(s->name, *n);        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);}----------------------------------------------------------------------This example is included in the distribution in `tests/test15.c`. It prints:    betty's id is 2Binary keys~~~~~~~~~~~We're using the term "binary" here to simply mean an arbitrary byte sequence.Your key field can have any data type. To uthash, it is just a sequence ofbytes.  We'll use the general macros `HASH_ADD` and `HASH_FIND` to demonstrateusage of a floating point key of type `double`..A key of type double----------------------------------------------------------------------#include <stdlib.h>#include <stdio.h>#include "uthash.h"typedef struct {    double veloc;     /* ... other data ... */    UT_hash_handle hh;} veloc_t;int main(int argc, char *argv[]) {    veloc_t *v, *v2, *veloc_table = NULL;    double x = 1/3.0;    v = malloc( sizeof(*v) );    v->veloc = x;    HASH_ADD(hh, veloc_table, veloc, sizeof(double), v);    HASH_FIND(hh, veloc_table, &x, sizeof(double), v2 );    if (v2) printf("found (%.2f)\n", v2->veloc);}----------------------------------------------------------------------Note that the general macros require the name of the `UT_hash_handle` to bepassed as the first argument (here, this is `hh`). The general macros are documented in <<Appendix_F,Appendix F: Macro Reference>>. Multi-field keys~~~~~~~~~~~~~~~~Your key can even comprise multiple contiguous fields. .A multi-field key----------------------------------------------------------------------#include <stdlib.h>    /* malloc       */#include <stddef.h>    /* offsetof     */#include <stdio.h>     /* printf       */#include <string.h>    /* memset       */#include "uthash.h"#define UTF32 1typedef struct {  UT_hash_handle hh;  int len;  char encoding;      /* these two fields */  int text[];         /* comprise the key */} msg_t;int main(int argc, char *argv[]) {    int keylen;    msg_t *msg, *msgs = NULL;    struct { char encoding; int text[]; } *lookup_key;    int beijing[] = {0x5317, 0x4eac};   /* UTF-32LE for 北京 */    /* allocate and initialize our structure */    msg = malloc( sizeof(msg_t) + sizeof(beijing) );    memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */    msg->len = sizeof(beijing);    msg->encoding = UTF32;    memcpy(msg->text, beijing, sizeof(beijing));    /* calculate the key length including padding, using formula */    keylen =   offsetof(msg_t, text)       /* offset of last key field */             + sizeof(beijing)             /* size of last key field */             - offsetof(msg_t, encoding);  /* offset of first key field */    /* add our structure to the hash table */    HASH_ADD( hh, msgs, encoding, keylen, msg);    /* look it up to prove that it worked :-) */    msg=NULL;    lookup_key = malloc(sizeof(*lookup_key) + sizeof(beijing));    memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing));    lookup_key->encoding = UTF32;    memcpy(lookup_key->text, beijing, sizeof(beijing));    HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg );    if (msg) printf("found \n");    free(lookup_key);}----------------------------------------------------------------------This example is included in the distribution in `tests/test22.c`.If you use multi-field keys, recognize that the compiler pads adjacent fields(by inserting unused space between them) in order to fulfill the alignmentrequirement of each field. For example a structure containing a `char` followedby an `int` will normally have 3 "wasted" bytes of padding after the char, inorder to make the `int` field start on a multiple-of-4 address (4 is the lengthof the int). .Calculating the length of a multi-field key:*******************************************************************************To determine the key length when using a multi-field key, you must include anyintervening structure padding the compiler adds for alignment purposes.An easy way to calculate the key length is to use the `offsetof` macro from`<stddef.h>`.  The formula is:     key length =   offsetof(last_key_field)                   + sizeof(last_key_field)                   - offsetof(first_key_field)In the example above, the `keylen` variable is set using this formula.*******************************************************************************When dealing with a multi-field key, you must zero-fill your structure before`HASH_ADD`'ing it to a hash table, or using its fields in a `HASH_FIND` key.In the previous example, `memset` is used to initialize the structure byzero-filling it. This zeroes out any padding between the key fields. If wedidn't zero-fill the structure, this padding would contain random values.  Therandom values would lead to `HASH_FIND` failures; as two "identical" keys willappear to mismatch if there are any differences within their padding.Structures in multiple hash tables----------------------------------A structure can be added to multiple hash tables. A few reasons you might dothis include:- each hash table may use an alternative key; - each hash table may have its own sort order; - or you might simply use multiple hash tables for grouping purposes.  E.g.,  you could have users in an `admin_users` and a `users` hash table. Your structure needs to have a `UT_hash_handle` field for each hash table towhich it might be added. You can name them anything. E.g.,  UT_hash_handle hh1, hh2;Alternative keys on the same structure~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~You might create a hash table keyed on an ID field, and another hash tablekeyed on username (if they are unique). You can add the same user structure toboth hash tables, then look up a user by either their unique ID or username..A structure with two alternative keys----------------------------------------------------------------------struct my_struct {    int id;                    /* key 1 */    char username[10];         /* key 2 */    UT_hash_handle hh1,hh2;    /* makes this structure hashable */};----------------------------------------------------------------------In the example above, the structure can now be added to two separate hashtables. In one hash, `id` is its key, while in the other hash, `username` isits key.  (There is no requirement that the two hashes have different keyfields. They could both use the same key, such as `id`).Notice the structure has two hash handles (`hh1` and `hh2`).  In the codebelow, notice that each hash handle is used exclusively with a particular hashtable.  (`hh1` is always used with the `users_by_id` hash, while `hh2` isalways used with the `users_by_name` hash table)..Two keys on a structure----------------------------------------------------------------------    struct my_struct *users_by_id = NULL, *users_by_name = NULL, *s;    int i;    char *name;    s = malloc(sizeof(struct my_struct));    s->id = 1;    strcpy(s->username, "thanson");    /* add the structure to both hash tables */    HASH_ADD(hh1, users_by_id, id, sizeof(int), s);    HASH_ADD(hh2, users_by_name, username, strlen(s->username), s);    /* lookup user by ID in the "users_by_id" hash table */    i=1;    HASH_FIND(hh1, users_by_id, &i, sizeof(int), s);    if (s) printf("found id %d: %s\n", i, s->username);    /* lookup user by username in the "users_by_name" hash table */    name = "thanson";    HASH_FIND(hh2, users_by_name, name, strlen(name), s);    if (s) printf("found user %s: %d\n", name, s->id);----------------------------------------------------------------------Multiple sort orders~~~~~~~~~~~~~~~~~~~~Extending the previous example, suppose we have many users in our `users_by_id`and our `users_by_name` hash, and that we want to sort each hash so that we can print the keys in order. We'd define two sort functions, then use `HASH_SRT`:  int sort_by_id(struct my_struct *a, struct my_struct *b) {    if (a->id == b->id) return 0;    return (a->id < b->id) ? -1 : 1;  }  int sort_by_name(struct my_struct *a, struct my_struct *b) {    return strcmp(a->username,b->username);  }  HASH_SRT(hh1, users_by_id, sort_by_id);  HASH_SRT(hh2, users_by_name, sort_by_name);  /* now iterate over users_by_id and users_by_name in sorted order */[[Appendix_A]]Appendix A: Built-in hash functions-----------------------------------Internally, a hash function transforms a key into a bucket number.  You don'thave to take any action to use the default hash function, Jenkin's hash. Some programs may benefit from using another of the built-in hash functions.There is a simple analysis utility included with uthash to help you determineif another hash function will give you better performance.You can use a different hash function by compiling your program with`-DHASH_FUNCTION=HASH_xyz` where `xyz` is one of the symbolic names listedbelow. E.g.,     cc -DHASH_FUNCTION=HASH_BER -o program program.c.Built-in hash functions[width="50%",cols="^5m,20",grid="none",options="header"]|===============================================================================|Symbol |   Name    |JEN    |   Jenkins (default)|BER    |   Bernstein|SAX    |   Shift-Add-Xor|OAT    |   One-at-a-time|FNV    |   Fowler/Noll/Vo

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -