使用 GSList 作为 GHashTable 值的不同方法
Different methods to use GSList as value of a GHashTable
给定代码片段:
#include <glib.h>
#include <stdio.h>
void print_city(gpointer value, gpointer data)
{
printf("%s, ", value);
}
void print(gpointer key, gpointer value, gpointer data)
{
printf("Here are some cities in %s: ", key);
g_slist_foreach((GSList *)value, (GFunc)print_city, 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,
"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_insert(hash,
"Texas",
g_slist_append(g_hash_table_lookup(hash, "Texas"), "Houston")
);
g_hash_table_insert(hash,
"Texas",
g_slist_append(g_hash_table_lookup(hash, "Texas"), "Austin")
);
g_hash_table_foreach(hash, print, NULL);
g_hash_table_foreach(hash, destroy, NULL);
g_hash_table_destroy(hash);
return 0;
}
我们可以注意到 main
函数中调用 g_hash_table_insert
的行看起来有点复杂,重复自身,因此我正在寻找代码替代方案来简化 value 参数。考虑到这一点,我第一次尝试更改代码如下(已添加评论)
GSList *list = NULL;
// Adding the first element to `list`
// list contains the pointer to the GSList head
list = g_slist_append(list, "Austin");
// Inserting the list (an address to a GSLIST) into
// the value of "Texas" key.
g_hash_table_insert(hash, "Texas", list);
// Retrieves the content of "Texas" key.
// (That is right now the pointer to the GSList head)
// and stores into value pointer
list = g_hash_table_lookup(hash, "Texas");
// Add the string "Houston" to the GSList and stores
// the new head at `value` to keep track of head.
list = g_slist_append(list, "Houston");
// Updates the 'key' Texas with list.
g_hash_table_insert(hash, "Texas", list);
看起来并没有好多少。我还在代码中添加了一些注释来描述我的理解。
问题一:我的理解(在评论中表达)是否正确?
问题2:保持代码的一致性,请问上面的代码有什么改进的方法吗?
我注意到我可以在第一个之后删除对 g_hash_table_insert
的所有调用,这可能会牺牲一些一致性。本例中的代码如下所示
GSList *list = NULL;
list = g_slist_append(list, "Austin");
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Houston");
问题 3:此更改如何影响一致性?
问题 4:这种变化会产生哪些行为?
无论如何,考虑到之前的代码片段,我试图让事情变得更多 "organized" 因此我到达了以下代码片段以更新 GHashTable 中的列表:
GSList *list = NULL;
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Austin");
list = g_slist_append(list, "Houston");
上面的代码看起来更有条理,但在工作中完全失败(甚至在 free
调用时触发段错误)。我不明白为什么最后一个片段失败了。
问题 5:为什么会出现段错误?
问题 6: 有没有不使用初始构造的更简单的方法来处理 GHashTables
中的 GSLists
?
GSList *list = NULL;
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Austin");
list = g_slist_append(list, "Houston");
您的哈希表只在此处包含 NULL。甚至前面的示例看起来也很不稳定,实际上不能保证有效:任何时候修改列表,头指针都可能改变。
完成您似乎想要的事情的最简单方法是先构建列表,然后将其添加到哈希表中:
GSList *list = g_slist_append(NULL, "Austin");
list = g_slist_append(list, "Houston");
g_hash_table_insert(hash, "Texas", list);
但是任何时候你想修改列表你都必须将它重新插入到哈希表中...我建议重新考虑你的数据结构选择:链接列表并不是真正适合任何东西(以及 GLib 实现正如您发现的那样特别烦人)。 GSequence、GArray(甚至 GHashTable with g_hash_table_add())可能是 GLib 中合适的替代品。
给定代码片段:
#include <glib.h>
#include <stdio.h>
void print_city(gpointer value, gpointer data)
{
printf("%s, ", value);
}
void print(gpointer key, gpointer value, gpointer data)
{
printf("Here are some cities in %s: ", key);
g_slist_foreach((GSList *)value, (GFunc)print_city, 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,
"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_insert(hash,
"Texas",
g_slist_append(g_hash_table_lookup(hash, "Texas"), "Houston")
);
g_hash_table_insert(hash,
"Texas",
g_slist_append(g_hash_table_lookup(hash, "Texas"), "Austin")
);
g_hash_table_foreach(hash, print, NULL);
g_hash_table_foreach(hash, destroy, NULL);
g_hash_table_destroy(hash);
return 0;
}
我们可以注意到 main
函数中调用 g_hash_table_insert
的行看起来有点复杂,重复自身,因此我正在寻找代码替代方案来简化 value 参数。考虑到这一点,我第一次尝试更改代码如下(已添加评论)
GSList *list = NULL;
// Adding the first element to `list`
// list contains the pointer to the GSList head
list = g_slist_append(list, "Austin");
// Inserting the list (an address to a GSLIST) into
// the value of "Texas" key.
g_hash_table_insert(hash, "Texas", list);
// Retrieves the content of "Texas" key.
// (That is right now the pointer to the GSList head)
// and stores into value pointer
list = g_hash_table_lookup(hash, "Texas");
// Add the string "Houston" to the GSList and stores
// the new head at `value` to keep track of head.
list = g_slist_append(list, "Houston");
// Updates the 'key' Texas with list.
g_hash_table_insert(hash, "Texas", list);
看起来并没有好多少。我还在代码中添加了一些注释来描述我的理解。
问题一:我的理解(在评论中表达)是否正确?
问题2:保持代码的一致性,请问上面的代码有什么改进的方法吗?
我注意到我可以在第一个之后删除对 g_hash_table_insert
的所有调用,这可能会牺牲一些一致性。本例中的代码如下所示
GSList *list = NULL;
list = g_slist_append(list, "Austin");
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Houston");
问题 3:此更改如何影响一致性?
问题 4:这种变化会产生哪些行为?
无论如何,考虑到之前的代码片段,我试图让事情变得更多 "organized" 因此我到达了以下代码片段以更新 GHashTable 中的列表:
GSList *list = NULL;
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Austin");
list = g_slist_append(list, "Houston");
上面的代码看起来更有条理,但在工作中完全失败(甚至在 free
调用时触发段错误)。我不明白为什么最后一个片段失败了。
问题 5:为什么会出现段错误?
问题 6: 有没有不使用初始构造的更简单的方法来处理 GHashTables
中的 GSLists
?
GSList *list = NULL;
g_hash_table_insert(hash, "Texas", list);
list = g_hash_table_lookup(hash, "Texas");
list = g_slist_append(list, "Austin");
list = g_slist_append(list, "Houston");
您的哈希表只在此处包含 NULL。甚至前面的示例看起来也很不稳定,实际上不能保证有效:任何时候修改列表,头指针都可能改变。
完成您似乎想要的事情的最简单方法是先构建列表,然后将其添加到哈希表中:
GSList *list = g_slist_append(NULL, "Austin");
list = g_slist_append(list, "Houston");
g_hash_table_insert(hash, "Texas", list);
但是任何时候你想修改列表你都必须将它重新插入到哈希表中...我建议重新考虑你的数据结构选择:链接列表并不是真正适合任何东西(以及 GLib 实现正如您发现的那样特别烦人)。 GSequence、GArray(甚至 GHashTable with g_hash_table_add())可能是 GLib 中合适的替代品。