免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4445 | 回复: 3
打印 上一主题 下一主题

[C] 关联数组 与 hash表 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-26 23:40 |只看该作者 |倒序浏览
我们知道关联数组的计算负责度为 一常量,这其中的关键是 因为是hash表的原因。

我一直理解的是,根据key 通过一个hash算法可以得到vlaue的存储位置。

但是今天可以一个应用中的一个dictionary 模块却不是这样子的,请大家解惑啊!

这是头文件


/*-------------------------------------------------------------------------*/
/**
   @file    dictionary.h
   @author  N. Devillard
   @date    Sep 2007
   @version $Revision: 1.12 $
   @brief   Implements a dictionary for string variables.

   This module implements a simple dictionary object, i.e. a list
   of string/string associations. This object is useful to store e.g.
   informations retrieved from a configuration file (ini files).
*/

/*--------------------------------------------------------------------------*/

/*
    $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
    $Author: ndevilla $
    $Date: 2007-11-23 21:37:00 $
    $Revision: 1.12 $
*/


#ifndef _DICTIONARY_H_
#define _DICTIONARY_H_

/*---------------------------------------------------------------------------
                                   Includes
 ---------------------------------------------------------------------------*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*---------------------------------------------------------------------------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;New types
&nbsp;---------------------------------------------------------------------------*/



/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Dictionary object

&nbsp;&nbsp;This object contains a list of string/string associations. Each
&nbsp;&nbsp;association is identified by a unique string key. Looking up values
&nbsp;&nbsp;in the dictionary is speeded up by the use of a (hopefully collision-free)
&nbsp;&nbsp;hash function.
&nbsp;*/

/*-------------------------------------------------------------------------*/
typedef struct _dictionary_ {
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/** Number of entries in dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size ;&nbsp;&nbsp;&nbsp;&nbsp;/** Storage size */
&nbsp;&nbsp;&nbsp;&nbsp;char &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**&nbsp;&nbsp;&nbsp;&nbsp;val ;&nbsp;&nbsp;&nbsp;&nbsp;/** List of string values */
&nbsp;&nbsp;&nbsp;&nbsp;char &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  key ;&nbsp;&nbsp;&nbsp;&nbsp;/** List of string keys */
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;hash ;&nbsp;&nbsp;&nbsp;&nbsp;/** List of hash values for keys */
} dictionary ;


/*---------------------------------------------------------------------------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function prototypes
&nbsp;---------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Compute the hash key for a string.
&nbsp;&nbsp;@param    key     Character string to use for key.
&nbsp;&nbsp;@return   1 unsigned int on at least 32 bits.

&nbsp;&nbsp;This hash function has been taken from an Article in Dr Dobbs Journal.
&nbsp;&nbsp;This is normally a collision-free function, distributing keys evenly.
&nbsp;&nbsp;The key is stored anyway in the struct so that collision can be avoided
&nbsp;&nbsp;by comparing the key itself in last resort.
&nbsp;*/

/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(char * key);

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Create a new dictionary object.
&nbsp;&nbsp;@param    size    Optional initial size of the dictionary.
&nbsp;&nbsp;@return   1 newly allocated dictionary objet.

&nbsp;&nbsp;This function allocates a new dictionary object of given size and returns
&nbsp;&nbsp;it. If you do not know in advance (roughly) the number of entries in the
&nbsp;&nbsp;dictionary, give size=0.
&nbsp;*/

/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size);

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Delete a dictionary object
&nbsp;&nbsp;@param    d   dictionary object to deallocate.
&nbsp;&nbsp;@return   void

&nbsp;&nbsp;Deallocate a dictionary object and all memory associated to it.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * vd);

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Get a value from a dictionary.
&nbsp;&nbsp;@param    d       dictionary object to search.
&nbsp;&nbsp;@param    key     Key to look for in the dictionary.
&nbsp;&nbsp;@param    def     Default value to return if key not found.
&nbsp;&nbsp;@return   1 pointer to internally allocated character string.

&nbsp;&nbsp;This function locates a key in a dictionary and returns a pointer to its
&nbsp;&nbsp;value, or the passed 'def' pointer if no such key can be found in
&nbsp;&nbsp;dictionary. The returned character pointer points to data internal to the
&nbsp;&nbsp;dictionary object, you should not try to free it or modify it.
&nbsp;*/

/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, char * key, char * def);


/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Set a value in a dictionary.
&nbsp;&nbsp;@param    d       dictionary object to modify.
&nbsp;&nbsp;@param    key     Key to modify or add.
&nbsp;&nbsp;@param    val     Value to add.
&nbsp;&nbsp;@return   int     0 if Ok, anything else otherwise

&nbsp;&nbsp;If the given key is found in the dictionary, the associated value is
&nbsp;&nbsp;replaced by the provided one. If the key cannot be found in the
&nbsp;&nbsp;dictionary, it is added to it.

&nbsp;&nbsp;It is Ok to provide a NULL value for val, but NULL values for the dictionary
&nbsp;&nbsp;or the key are considered as errors: the function will return immediately
&nbsp;&nbsp;in such a case.

&nbsp;&nbsp;Notice that if you dictionary_set a variable to NULL, a call to
&nbsp;&nbsp;dictionary_get will return a NULL value: the variable will be found, and
&nbsp;&nbsp;its value (NULL) is returned. In other words, setting the variable
&nbsp;&nbsp;content to NULL is equivalent to deleting the variable from the
&nbsp;&nbsp;dictionary. It is not possible (in this implementation) to have a key in
&nbsp;&nbsp;the dictionary without value.

&nbsp;&nbsp;This function returns non-zero in case of failure.
&nbsp;*/

/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * vd, char * key, char * val);

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Delete a key in a dictionary
&nbsp;&nbsp;@param    d       dictionary object to modify.
&nbsp;&nbsp;@param    key     Key to remove.
&nbsp;&nbsp;@return   void

&nbsp;&nbsp;This function deletes a key in a dictionary. Nothing is done if the
&nbsp;&nbsp;key cannot be found.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, char * key);


/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Dump a dictionary to an opened file pointer.
&nbsp;&nbsp;@param    d   Dictionary to dump
&nbsp;&nbsp;@param    f   Opened file pointer.
&nbsp;&nbsp;@return   void

&nbsp;&nbsp;Dumps a dictionary onto an opened file pointer. Key pairs are printed out
&nbsp;&nbsp;as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
&nbsp;&nbsp;output file pointers.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out);

#endif

论坛徽章:
0
2 [报告]
发表于 2009-01-26 23:45 |只看该作者
这是 源码

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;&nbsp;@file&nbsp;&nbsp;&nbsp;&nbsp;dictionary.c
&nbsp;&nbsp;&nbsp;@author&nbsp;&nbsp;&nbsp;&nbsp;N. Devillard
&nbsp;&nbsp;&nbsp;@date&nbsp;&nbsp;&nbsp;&nbsp;Sep 2007
&nbsp;&nbsp;&nbsp;@version&nbsp;&nbsp;&nbsp;&nbsp;$Revision: 1.27 $
&nbsp;&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Implements a dictionary for string variables.

&nbsp;&nbsp;&nbsp;This module implements a simple dictionary object, i.e. a list
&nbsp;&nbsp;&nbsp;of string/string associations. This object is useful to store e.g.
&nbsp;&nbsp;&nbsp;informations retrieved from a configuration file (ini files).
*/

/*--------------------------------------------------------------------------*/

/*
&nbsp;&nbsp;&nbsp;&nbsp;$Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
&nbsp;&nbsp;&nbsp;&nbsp;$Revision: 1.27 $
*/

/*---------------------------------------------------------------------------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Includes
&nbsp;---------------------------------------------------------------------------*/

#include "dictionnary.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/** Maximum value size for integers and doubles. */
#define MAXVALSZ&nbsp;&nbsp;&nbsp;&nbsp;1024

/** Minimal allocated number of entries in a dictionary */
#define DICTMINSZ&nbsp;&nbsp;&nbsp;&nbsp;128

/** Invalid key token */
#define DICT_INVALID_KEY    ((char*)-1)

/*---------------------------------------------------------------------------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsprivate functions
&nbsp;---------------------------------------------------------------------------*/


/* Doubles the allocated size associated to a pointer */
/* 'size' is the current allocated size. */
static void * mem_double(void * ptr, int size)
{
&nbsp;&nbsp;&nbsp;&nbsp;void * newptr ;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;newptr = calloc(2*size, 1);
&nbsp;&nbsp;&nbsp;&nbsp;if (newptr==NULL) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;memcpy(newptr, ptr, size);
&nbsp;&nbsp;&nbsp;&nbsp;free(ptr);
&nbsp;&nbsp;&nbsp;&nbsp;return newptr ;
}

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Duplicate a string
&nbsp;&nbsp;@param    s String to duplicate
&nbsp;&nbsp;@return   Pointer to a newly allocated string, to be freed with free()

&nbsp;&nbsp;This is a replacement for strdup(). This implementation is provided
&nbsp;&nbsp;for systems that do not have it.
&nbsp;*/

/*--------------------------------------------------------------------------*/
static char * xstrdup(char * s)
{
&nbsp;&nbsp;&nbsp;&nbsp;char * t ;
&nbsp;&nbsp;&nbsp;&nbsp;if (!s)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;t = (char*)malloc(strlen(s)+1) ;
&nbsp;&nbsp;&nbsp;&nbsp;if (t) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(t,s);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return t ;
}

/*---------------------------------------------------------------------------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function codes
&nbsp;---------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Compute the hash key for a string.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Character string to use for key.
&nbsp;&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;1 unsigned int on at least 32 bits.

&nbsp;&nbsp;This hash function has been taken from an Article in Dr Dobbs Journal.
&nbsp;&nbsp;This is normally a collision-free function, distributing keys evenly.
&nbsp;&nbsp;The key is stored anyway in the struct so that collision can be avoided
&nbsp;&nbsp;by comparing the key itself in last resort.
&nbsp;*/

/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(char * key)
{
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len ;
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;&nbsp;&nbsp;&nbsp;hash ;
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;

&nbsp;&nbsp;&nbsp;&nbsp;len = strlen(key);
&nbsp;&nbsp;&nbsp;&nbsp;for (hash=0, i=0 ; i<len ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash += (unsigned)key[i] ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash += (hash<<10);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash ^= (hash>>6) ;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;hash += (hash <<3);
&nbsp;&nbsp;&nbsp;&nbsp;hash ^= (hash >>11);
&nbsp;&nbsp;&nbsp;&nbsp;hash += (hash <<15);
&nbsp;&nbsp;&nbsp;&nbsp;return hash ;
}

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Create a new dictionary object.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;&nbsp;&nbsp;&nbsp;Optional initial size of the dictionary.
&nbsp;&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;1 newly allocated dictionary objet.

&nbsp;&nbsp;This function allocates a new dictionary object of given size and returns
&nbsp;&nbsp;it. If you do not know in advance (roughly) the number of entries in the
&nbsp;&nbsp;dictionary, give size=0.
&nbsp;*/

/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size)
{
&nbsp;&nbsp;&nbsp;&nbsp;dictionary&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;d ;

&nbsp;&nbsp;&nbsp;&nbsp;/* If no size was specified, allocate space for DICTMINSZ */
&nbsp;&nbsp;&nbsp;&nbsp;if (size<DICTMINSZ) size=DICTMINSZ ;

&nbsp;&nbsp;&nbsp;&nbsp;if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return NULL;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;d->size = size ;
&nbsp;&nbsp;&nbsp;&nbsp;d->val  = (char **)calloc(size, sizeof(char*));
&nbsp;&nbsp;&nbsp;&nbsp;d->key  = (char **)calloc(size, sizeof(char*));
&nbsp;&nbsp;&nbsp;&nbsp;d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
&nbsp;&nbsp;&nbsp;&nbsp;return d ;
}

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Delete a dictionary object
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;dictionary object to deallocate.
&nbsp;&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;void

&nbsp;&nbsp;Deallocate a dictionary object and all memory associated to it.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * d)
{
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;

&nbsp;&nbsp;&nbsp;&nbsp;if (d==NULL) return ;
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]!=NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(d->key[i]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->val[i]!=NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(d->val[i]);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;free(d->val);
&nbsp;&nbsp;&nbsp;&nbsp;free(d->key);
&nbsp;&nbsp;&nbsp;&nbsp;free(d->hash);
&nbsp;&nbsp;&nbsp;&nbsp;free(d);
&nbsp;&nbsp;&nbsp;&nbsp;return ;
}

论坛徽章:
0
3 [报告]
发表于 2009-01-26 23:46 |只看该作者
/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Get a value from a dictionary.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dictionary object to search.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Key to look for in the dictionary.
&nbsp;&nbsp;@param    def     Default value to return if key not found.
&nbsp;&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;1 pointer to internally allocated character string.

&nbsp;&nbsp;This function locates a key in a dictionary and returns a pointer to its
&nbsp;&nbsp;value, or the passed 'def' pointer if no such key can be found in
&nbsp;&nbsp;dictionary. The returned character pointer points to data internal to the
&nbsp;&nbsp;dictionary object, you should not try to free it or modify it.
&nbsp;*/

/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, char * key, char * def)
{
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;&nbsp;&nbsp;&nbsp;hash ;
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;

&nbsp;&nbsp;&nbsp;&nbsp;hash = dictionary_hash(key);
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]==NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Compare hash */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (hash==d->hash[i]) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Compare string, to avoid hash collisions */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!strcmp(key, d->key[i])) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return d->val[i] ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return def ;
}

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief    Set a value in a dictionary.
&nbsp;&nbsp;@param    d       dictionary object to modify.
&nbsp;&nbsp;@param    key     Key to modify or add.
&nbsp;&nbsp;@param    val     Value to add.
&nbsp;&nbsp;@return   int     0 if Ok, anything else otherwise

&nbsp;&nbsp;If the given key is found in the dictionary, the associated value is
&nbsp;&nbsp;replaced by the provided one. If the key cannot be found in the
&nbsp;&nbsp;dictionary, it is added to it.

&nbsp;&nbsp;It is Ok to provide a NULL value for val, but NULL values for the dictionary
&nbsp;&nbsp;or the key are considered as errors: the function will return immediately
&nbsp;&nbsp;in such a case.

&nbsp;&nbsp;Notice that if you dictionary_set a variable to NULL, a call to
&nbsp;&nbsp;dictionary_get will return a NULL value: the variable will be found, and
&nbsp;&nbsp;its value (NULL) is returned. In other words, setting the variable
&nbsp;&nbsp;content to NULL is equivalent to deleting the variable from the
&nbsp;&nbsp;dictionary. It is not possible (in this implementation) to have a key in
&nbsp;&nbsp;the dictionary without value.

&nbsp;&nbsp;This function returns non-zero in case of failure.
&nbsp;*/

/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * d, char * key, char * val)
{
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;&nbsp;&nbsp;&nbsp;hash ;

&nbsp;&nbsp;&nbsp;&nbsp;if (d==NULL || key==NULL) return -1 ;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/* Compute hash for this key */
&nbsp;&nbsp;&nbsp;&nbsp;hash = dictionary_hash(key) ;
&nbsp;&nbsp;&nbsp;&nbsp;/* Find if value is already in dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;if (d->n>0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]==NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (hash==d->hash[i]) { /* Same hash value */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!strcmp(key, d->key[i])) {&nbsp;&nbsp;&nbsp;&nbsp; /* Same key */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Found a value: modify and return */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->val[i]!=NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(d->val[i]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->val[i] = val ? xstrdup(val) : NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Value has been modified: return */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0 ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;/* Add a new value */
&nbsp;&nbsp;&nbsp;&nbsp;/* See if dictionary needs to grow */
&nbsp;&nbsp;&nbsp;&nbsp;if (d->n==d->size) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Reached maximum size: reallocate dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Cannot grow dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1 ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Double size */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->size *= 2 ;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;/* Insert key in the first empty slot */
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]==NULL) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Add key here */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;/* Copy key */
&nbsp;&nbsp;&nbsp;&nbsp;d->key[i]  = xstrdup(key);
&nbsp;&nbsp;&nbsp;&nbsp;d->val[i]  = val ? xstrdup(val) : NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;d->hash[i] = hash;
&nbsp;&nbsp;&nbsp;&nbsp;d->n ++ ;
&nbsp;&nbsp;&nbsp;&nbsp;return 0 ;
}

论坛徽章:
0
4 [报告]
发表于 2009-01-26 23:49 |只看该作者
/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Delete a key in a dictionary
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dictionary object to modify.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Key to remove.
&nbsp;&nbsp;@return   void

&nbsp;&nbsp;This function deletes a key in a dictionary. Nothing is done if the
&nbsp;&nbsp;key cannot be found.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, char * key)
{
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;&nbsp;&nbsp;&nbsp;hash ;
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;

&nbsp;&nbsp;&nbsp;&nbsp;if (key == NULL) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;hash = dictionary_hash(key);
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]==NULL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Compare hash */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (hash==d->hash[i]) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Compare string, to avoid hash collisions */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!strcmp(key, d->key[i])) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Found key */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (i>=d->size)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Key not found */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ;

&nbsp;&nbsp;&nbsp;&nbsp;free(d->key[i]);
&nbsp;&nbsp;&nbsp;&nbsp;d->key[i] = NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;if (d->val[i]!=NULL) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(d->val[i]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->val[i] = NULL ;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;d->hash[i] = 0 ;
&nbsp;&nbsp;&nbsp;&nbsp;d->n -- ;
&nbsp;&nbsp;&nbsp;&nbsp;return ;
}

/*-------------------------------------------------------------------------*/
/**
&nbsp;&nbsp;@brief&nbsp;&nbsp;&nbsp;&nbsp;Dump a dictionary to an opened file pointer.
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;Dictionary to dump
&nbsp;&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;f&nbsp;&nbsp;&nbsp;&nbsp;Opened file pointer.
&nbsp;&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;void

&nbsp;&nbsp;Dumps a dictionary onto an opened file pointer. Key pairs are printed out
&nbsp;&nbsp;as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
&nbsp;&nbsp;output file pointers.
&nbsp;*/

/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out)
{
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;

&nbsp;&nbsp;&nbsp;&nbsp;if (d==NULL || out==NULL) return ;
&nbsp;&nbsp;&nbsp;&nbsp;if (d->n<1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(out, "empty dictionary\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<d->size ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (d->key[i]) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(out, "%20s\t[%s]\n",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->key[i],
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d->val[i] ? d->val[i] : "UNDEF");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return ;
}


/* Test code */
#ifdef TESTDIC
#define NVALS 20000
int main(int argc, char *argv[])
{
&nbsp;&nbsp;&nbsp;&nbsp;dictionary&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;d ;
&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;val ;
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i ;
&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cval[90] ;

&nbsp;&nbsp;&nbsp;&nbsp;/* Allocate dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;printf("allocating...\n");
&nbsp;&nbsp;&nbsp;&nbsp;d = dictionary_new(0);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/* Set values in dictionary */
&nbsp;&nbsp;&nbsp;&nbsp;printf("setting %d values...\n", NVALS);
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<NVALS ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(cval, "%04d", i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dictionary_set(d, cval, "salut");
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;printf("getting %d values...\n", NVALS);
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<NVALS ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(cval, "%04d", i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val = dictionary_get(d, cval, DICT_INVALID_KEY);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (val==DICT_INVALID_KEY) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("cannot get value for key [%s]\n", cval);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;printf("unsetting %d values...\n", NVALS);
&nbsp;&nbsp;&nbsp;&nbsp;for (i=0 ; i<NVALS ; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(cval, "%04d", i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dictionary_unset(d, cval);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (d->n != 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("error deleting values\n");
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;printf("deallocating...\n");
&nbsp;&nbsp;&nbsp;&nbsp;dictionary_del(d);
&nbsp;&nbsp;&nbsp;&nbsp;return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP