原文地址: http://hi.baidu.com/study_together/blog/item/7db6da1d7acfbbf91ad5763e.html
编译:gcc -g -Wall -O0 fuck.c -o fuck `pkg-config –libs –cflags glib-2.0`
1
一些简单的散列表操作 有错误需要调试
这里是一些示例,可以生动地展示以上的理论:
#include < glib.h >
#include < stdio.h >
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(hash, " Virginia " , " Richmond " );
g_hash_table_insert(hash, " Texas " , " Austin " );
g_hash_table_insert(hash, " Ohio " , " Columbus " );
printf( " There are %d keys in the hash\n " , g_hash_table_size(hash));
printf( " The capital of Texas is %s\n " , g_hash_table_lookup(hash, " Texas " ));
gboolean found = g_hash_table_remove(hash, " Virginia " );
printf( " The value 'Virginia' was %sfound and removed\n " , found ? "" : " not " );
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
There are 3 keys in the hash
The capital of Texas is Austin
The value 'Virginia' was found and removed
2
插入和替换值
当使用 g_hash_table_insert 插入键时,GHashTable 首先检查那个键是否已经存在。如果已经存在,那么那个值会被替换,
而键不会被替换。如果希望同时替换键和值,那么需要使用 g_hash_table_replace。它稍有不同,因此在下面同时展示了二者:
#include < glib.h >
#include < stdio.h >
static char * texas_1, * texas_2;
void key_destroyed(gpointer data) {
printf( " Got a key destroy call for %s\n " , data == texas_1 ? " texas_1 " : " texas_2 " );
}
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)key_destroyed, NULL);
texas_1 = g_strdup( " Texas " );
texas_2 = g_strdup( " Texas " );
g_hash_table_insert(hash, texas_1, " Austin " );
printf( " Calling insert with the texas_2 key\n " );
g_hash_table_insert(hash, texas_2, " Houston " );
printf( " Calling replace with the texas_2 key\n " );
g_hash_table_replace(hash, texas_2, " Houston " );
printf( " Destroying hash, so goodbye texas_2\n " );
g_hash_table_destroy(hash);
g_free(texas_1);
g_free(texas_2);
return 0 ;
}
***** Output *****
Calling insert with the texas_2 key
Got a key destroy call for texas_2
Calling replace with the texas_2 key
Got a key destroy call for texas_1
Destroying hash, so goodbye texas_2
Got a key destroy call for texas_2
3
遍历 键/值 对
有时需要遍历所有的 键/值 对。这里是如何使用 g_hash_table_foreach 来完成那项任务:
#include < glib.h >
#include < stdio.h >
void iterator(gpointer key, gpointer value, gpointer user_data) {
printf(user_data, * (gint * )key, value);
}
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new(g_int_hash, g_int_equal);
gint * k_one = g_new(gint, 1 ), * k_two = g_new(gint, 1 ), * k_three = g_new(gint, 1 );
* k_one = 1 , * k_two = 2 , * k_three = 3 ;
g_hash_table_insert(hash, k_one, " one " );
g_hash_table_insert(hash, k_two, " four " );
g_hash_table_insert(hash, k_three, " nine " );
g_hash_table_foreach(hash, (GHFunc)iterator, " The square of %d is %s\n " );
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
The square of 1 is one
The square of 2 is four
The square of 3 is nine
4
查找条目
使用 g_hash_table_find 函数来查找某个特定的值。这个函数支持查看每一个 键/值 对,直到定位到期望的值。这里是一个示例:
#include < glib.h >
#include < stdio.h >
void value_destroyed(gpointer data) {
printf( " Got a value destroy call for %d\n " , GPOINTER_TO_INT(data));
}
gboolean finder(gpointer key, gpointer value, gpointer user_data) {
return (GPOINTER_TO_INT(key) + GPOINTER_TO_INT(value)) == 42 ;
}
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL,
(GDestroyNotify)value_destroyed);
g_hash_table_insert(hash, GINT_TO_POINTER( 6 ), GINT_TO_POINTER( 36 ));
g_hash_table_insert(hash, GINT_TO_POINTER( 10 ), GINT_TO_POINTER( 12 ));
g_hash_table_insert(hash, GINT_TO_POINTER( 20 ), GINT_TO_POINTER( 22 ));
gpointer item_ptr = g_hash_table_find(hash, (GHRFunc)finder, NULL);
gint item = GPOINTER_TO_INT(item_ptr);
printf( " %d + %d == 42\n " , item, 42 - item);
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
36 + 6 == 42
Got a value destroy call for 36
Got a value destroy call for 22
Got a value destroy call for 12
5
难处理的情形:从表中删除
偶尔可能需要从一个 GHashTable 中删除某个条目,但却没有获得 GHashTable 所提供的任意 GDestroyNotify 函数的回调。
要完成此任务,或者可以根据具体的键使用 g_hash_table_steal,或者根据所有匹配某个条件的键使用 g_hash_table_foreach_steal。
#include < glib.h >
#include < stdio.h >
gboolean wide_open(gpointer key, gpointer value, gpointer user_data) {
return TRUE;
}
void key_destroyed(gpointer data) {
printf( " Got a GDestroyNotify callback\n " );
}
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)key_destroyed,
(GDestroyNotify)key_destroyed);
g_hash_table_insert(hash, " Texas " , " Austin " );
g_hash_table_insert(hash, " Virginia " , " Richmond " );
g_hash_table_insert(hash, " Ohio " , " Columbus " );
g_hash_table_insert(hash, " Oregon " , " Salem " );
g_hash_table_insert(hash, " New York " , " Albany " );
printf( " Removing New York, you should see two callbacks\n " );
g_hash_table_remove(hash, " New York " );
if (g_hash_table_steal(hash, " Texas " )) {
printf( " Texas has been stolen, %d items remaining\n " , g_hash_table_size(hash));
}
printf( " Stealing remaining items\n " );
g_hash_table_foreach_steal(hash, (GHRFunc)wide_open, NULL);
printf( " Destroying the GHashTable, but it's empty, so no callbacks\n " );
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
Removing New York, you should see two callbacks
Got a GDestroyNotify callback
Got a GDestroyNotify callback
Texas has been stolen, 3 items remaining
Stealing remaining items
Destroying the GHashTable, but it's empty, so no callbacks
6
高级查找:找到键和值
针对需要从表中同时获得键和值的情况,GHashTable 提供了一个 g_hash_table_lookup_extended 函数。
它与 g_hash_table_lookup 非常类似,但要接受更多两个参数。这些都是“out”参数;也就是说,它们是双重间接指针,当数据被定位时将指向它
。这里是它的工作方式:
#include < glib.h >
#include < stdio.h >
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(hash, " Texas " , " Austin " );
g_hash_table_insert(hash, " Virginia " , " Richmond " );
g_hash_table_insert(hash, " Ohio " , " Columbus " );
char * state = NULL;
char * capital = NULL;
char ** key_ptr = & state;
char ** value_ptr = & capital;
gboolean result = g_hash_table_lookup_extended(hash, " Ohio " , (gpointer * )key_ptr, (gpointer * )value_ptr);
if (result) {
printf( " Found that the capital of %s is %s\n " , capital, state);
}
if ( ! g_hash_table_lookup_extended(hash, " Vermont " , (gpointer * )key_ptr, (gpointer * )value_ptr)) {
printf( " Couldn't find Vermont in the hash table\n " );
}
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
Found that the capital of Columbus is Ohio
Couldn't find Vermont in the hash table
7
每个键多个值 有错误需要调试
到目前为止已经介绍了每个键只拥有一个值的散列。不过有时您需要让一个键持有多个值。当出现这种需求时,
使用 GSList 作为值并及 GSList 添加新的值通常是一个好的解决方案。不过,这需要稍多一些工作,如本例中所示:
#include < glib.h >
#include < stdio.h >
void print(gpointer key, gpointer value, gpointer data) {
printf( " Here are some cities in %s: " , key);
g_slist_foreach((GSList * )value, (GFunc)printf, NULL);
printf( " \n " );
}
void destroy(gpointer key, gpointer value, gpointer data) {
printf( " Freeing a GSList, first item is %s\n " , ((GSList * )value) -> data);
g_slist_free(value);
}
int main( int argc, char ** argv) {
GHashTable * hash = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(hash, " Texas " ,
g_slist_append(g_hash_table_lookup(hash, " Texas " ), " Austin " ));
g_hash_table_insert(hash, " Texas " ,
g_slist_append(g_hash_table_lookup(hash, " Texas " ), " Houston " ));
g_hash_table_insert(hash, " Virginia " ,
g_slist_append(g_hash_table_lookup(hash, " Virginia " ), " Richmond " ));
g_hash_table_insert(hash, " Virginia " ,
g_slist_append(g_hash_table_lookup(hash, " Virginia " ), " Keysville " ));
g_hash_table_foreach(hash, print, NULL);
g_hash_table_foreach(hash, destroy, NULL);
g_hash_table_destroy(hash);
return 0 ;
}
***** Output *****
Here are some cities in Texas: Austin Houston
Here are some cities in Virginia: Richmond Keysville
Freeing a GSList, first item is Austin
Freeing a GSList, first item is Richmond
完