glib 散列表

原文地址: 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

posted @ 2011-07-09 21:41  wangkangluo1  阅读(1407)  评论(0编辑  收藏  举报