看看wiki上"Hash table"的解釋, 感覺實做上似乎不是那麼容易, 尤其是hash function的設計, 但多數的程式語言, 如perl, java, c#, 都提供了hash相關的library. 在linux下, 也有一系列的"hash table management" APIs.
以下提供一個簡單的範例
my_hash.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>
typedef struct _node_t
{
char key[16];
char value[16];
}node_t;
static node_t *node_list = NULL;
static struct hsearch_data htab;
void set_node(char *name, char *value)
{
ENTRY e, *ep;
memset(&e, 0, sizeof(ENTRY));
e.key = name;
hsearch_r(e, FIND, &ep, &htab);
if(ep)
ep->data = value;
else
{
e.data = value;
hsearch_r(e, ENTER, &ep, &htab);
}
}
void get_node(char *name, char *buf)
{
ENTRY e={NULL,NULL}, *ep;
e.key = name;
hsearch_r(e, FIND, &ep, &htab);
if (ep && ep->data)
strcpy(buf, ep->data);
else
strcpy(buf, "");
}
void release_htab()
{
if (node_list) free(node_list);
hdestroy_r(&htab);
}
void create_htab(char *fpath)
{
FILE *fp = NULL;
int nel=0;
fp = fopen(fpath, "r");
if (!fp)
{
CM_DBG("Cannot open %s\n", fpath);
return;
}
release_htab();
// Get the total number
while(!feof(fp) && fgets(str, BUF_SIZE, fp))
{
nel++;
}
if(!hcreate_r(nel, &htab))
return;
node_list = malloc(sizeof(node_t)*nel);
memset(node_list, 0, (sizeof(node_t)*nel));
rewind(fp);
char str[256] = {0};
char *ptr=NULL, *saveptr=NULL;
node_t *p_node = NULL;
int i = 0;
while(!feof(fp) && fgets(str, BUF_SIZE, fp))
{
p_node = (node_t *)(node_list+i);
//The string format: Name,PhoneNo
ptr = strtok_r(str, ",", &saveptr); // Name
if (ptr)
strcpy(p_node->key, ptr);
else
continue;
ptr = strtok_r(NULL, ",\n", &saveptr); // Phone No
if (ptr)
strcat(p_node->value, ptr);
else
continue;
set_node(p_node->key, p_node->value); //Put into hash table
i++;
}
}
其中, 要注意的地方在於, 塞hash table時, 需要動態配置記憶體空間來儲存值組(key, value), 但hdestroy並不會釋放動態配置的記憶體空間, 使用者需要自己free. 在範例程式中, 單純開了一個大塊的空間去存值, 但比較好的作法,可能是用linked list去紀錄各個值組, 這樣比較不用怕浪費太多記憶體空間或是buffer不夠大的問題.參考資料:
[1] hsearch_r.c
沒有留言:
張貼留言