c - g_hash_table_insert 似乎覆盖了以前插入的值
问题描述
我是 GLIB 库的新手。g_hash_table_insert()
似乎覆盖了以前插入的值。当我打印出保存数据的键和值时,键仍然是唯一的且未更改,但值都相同。我将一个struct
类型存储到其中GHashtable
,这是它的结构:
struct _DsectionEntity {
...
int entity_type;
int sequence_number;
...
};
typedef struct _DsectionEntity DsectionEntity;
DsectionEntity
我逐行解析 IGES 模型文件,并在解析 IGES 文件的 D 部分的 2 行后创建对象。我使用对象的序列号作为键,使用整个对象作为值。创建哈希表和插入值的代码如下:
void
get_dsection(IgesFile *fp, DsectionEntity *ds)
{
char *line1 = malloc(91);
char *line2 = malloc(91);
/* dsection_ht GHashtable declared as a global var and initialized to NULL */
dsection_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
line1 = get_line(fp, line1);
while (line1) {
if (line1[72] == 'D') {
line2 = get_line(fp, line2);
/* create Object */
parser_dsection_new(ds, line1, line2);
/* insert Object into the hashtable */
parser_add_ds_object(dsection_ht, ds);
line1 = get_line(fp, line1);
} else {
line1 = get_line(fp, line1);
}
}
}
插入代码:
void
parser_add_ds_object(GHashTable * ht, DsectionEntity *dsec_entity)
{
// printf("KEY : %d\n", GPOINTER_TO_INT(GINT_TO_POINTER(dsec_entity->sequence_number)));
// printf("SQ : %d\n", dsec_entity->sequence_number);
// printf("Entity : %d\n", dsec_entity->entity_type);
// printf("\n");
g_hash_table_insert(ht, GINT_TO_POINTER(dsec_entity->sequence_number), (gpointer)dsec_entity);
}
void
print_values(gpointer key, gpointer value, gpointer userdata)
{
int realkey = GPOINTER_TO_INT(key);
DsectionEntity *realvalue = (DsectionEntity *)value;
printf("KEY : %d\n", realkey);
printf("SQ : %d\n", realvalue->sequence_number);
printf("Entity : %d\n", realvalue->entity_type);
printf("====================================\n");
}
如果我显示使用g_hash_table_foreach(dsection_ht, print_values, NULL)
并print_values()
显示在上面。我得到:
具有重复sequence_number
和的对象entity_type
是最后添加到的对象GHashtable
(如图1所示)。Valgrind 没有显示错误,那么可能是什么问题?
文件格式为 IGES(初始图形交换规范)。代码parser_dsection_new()
:
void
parser_dsection_new(DsectionEntity *dsec_entity, char *line1, char *line2)
{
char substr[10];
get_field(line1, substr, 1, 8);
dsec_entity->entity_type = utils_to_int(substr);
// ...
get_field(line1, substr, 74, 8);
dsec_entity->sequence_number = utils_to_int(substr);
get_field(line1, substr, 9, 8);
dsec_entity->line_weight = utils_to_int(substr);
get_field(line1, substr, 17, 8);
dsec_entity->color = utils_to_int(substr);
get_field(line1, substr, 57, 8);
dsec_entity->entity_label = substr;
// ...
}
解决方案
将新的键和值插入 GHashTable。
如果键已存在于 GHashTable 中,则其当前值将替换为新值。如果您在创建 GHashTable 时提供了 value_destroy_func,则使用该函数释放旧值。如果您在创建 GHashTable 时提供了 key_destroy_func,则使用该函数释放传递的密钥。
因此,g_hash_table_insert()
API 应该用新值替换现有值。
但是,您的问题是您只使用一个实例,DsectionEntity
即解析、插入等,而每次您想在哈希中插入一个新的键/值对时,您都应该有一个唯一的实例。在您的代码中,相同的实例被覆盖,这就是您只看到最新值的原因。使用唯一的实例,它会工作。
g_hash_table_new_full()
您可以像这样使用默认删除功能g_hash_table_remove_all()
:
// Create hash table with default delete callbacks
ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, g_free, g_free);
// ~~~~~~ ~~~~~~
// Allocate new entry
ds = (DsectionEntity*) malloc( sizeof(DsectionEntity) );
// Populate entry
// ...
// Insert entry in hash table
g_hash_table_insert( ht,
GINT_TO_POINTER( ds->sequence_number ),
(gpointer) ds);
// ^^^ Do check the return value of g_hash_table_insert
// Remove hash table at the end
g_hash_table_remove_all( ht );
检查此示例以获得指导。
选择:
您可能想探索UT Hash作为替代哈希表解决方案。
推荐阅读
- java - 如何在 Android 的一个 FirestoreRecyclerAdapter 中包含两个模型类曲目和艺术家?
- python - 在 python selenium 中搜索内部元素似乎不起作用
- prolog - 变量 = 术语复合序言
- android - 避免从 JSON 数组响应中删除重复值
- javascript - 刷新时可能html页面状态中的元素没有改变?
- elasticsearch - Elasticsearch 嵌套布尔查询
- unit-testing - 白盒测试 - 基础覆盖率
- python - 对于新的 linux 用户,在 python 中获取登录名的简单方法是什么?
- javascript - 反应 | 功能组件抛出错误 useState Object(...) is not a function
- sql - 我有两个查询要优化,它们在生产中运行很长时间。我已经使用了表中存在的所有可能的索引。有什么建议么?