在C中使用HashMap来存储字符串 - 整数映射一次,并用于整个程序运行
我有我自己的执行C hash_map_t结构,我可以使用如下?在C中使用HashMap来存储字符串 - 整数映射一次,并用于整个程序运行
// string value allocator
allocator_t *str_value_allocator;
allocator_init(&str_value_allocator, string_allocate_handler, string_deallocate_handler);
str_hash_map_init(&str_hash_map, str_value_allocator, 5);
str_hash_map_put(str_hash_map, test_key, test_val, strlen(test_val));
str_hash_map_get(str_hash_map, test_key, NULL)
str_hash_map_remove(str_hash_map, test_key)
str_hash_map_free(str_hash_map);
我想用此散列映射函数象下面这样:
void handle_keyboard_input(char **tokens, size_t num_tokens) {
char *virtual_key_name = strtok(tokens[1], " ");
size_t num_flags = 0;
char **modifier_flags = str_split(tokens[2], ", ", &num_flags);
// map virtual_key_name (char *) to virtual_key code (int)
// foreach modifier flag (char *) map to modifier flag code (int)
}
我能为KEY_NAME创建2个hash_maps - > key_code映射和flag_name - > flag_code映射。问题是我不希望每次调用请求处理程序函数时创建此标志,但只有一个数据结构实例从函数的第一次调用开始,并且在连续的函数调用中,我希望重新使用此数据结构(数据存储)已经创建。
我的hash_map是在堆上创建的,因此不可能像在库源代码文件内某处的数组那样分配它。
在Java甚至C++中,我可以创建一些单例模式或静态成员,但是这种概念在C语言中不可用。也许我可以在程序启动的某个地方在程序启动时创建这个hash_map,但我怎样才能传递对程序使用的库的引用。
我最近的想法是使用static hash_map_t variable inside my handle_keyboard_input function
,并以某种方式初始化它只有当它是NULL(第一个函数调用),并且如果在连续调用中变量不是NULL,只是重用以前初始化的hash_map_t结构。
这个问题最好的解决方法是什么?
UPDATE
我可以用这样的代码?
static str_hash_map_t *virtual_keys_map = NULL;
static str_hash_map_t *modifier_flags_map = NULL;
if (virtual_keys_map == NULL) {
virtual_keys_map_init(&virtual_keys_map);
}
if (modifier_flags_map == NULL) {
modifier_flags_map_init(&modifier_flags_map);
}
是,上面的代码导致该指针将只是一次初始化(或者,如果将它们设置为NULL
,条件会true
,它会再次INIT),留在记忆即使你的函数外。
变量的使用期限从程序流第一次遇到声明开始,到程序结束时结束 - 换句话说,它们是全局变量。
此变量的名称只能在函数内访问,并且没有链接。
如果您认为您需要全局访问的变量,仍然需要非常小心。 Read here。
static str_hash_map_t *virtual_keys_map = NULL;
static str_hash_map_t *modifier_flags_map = NULL;
if(virtual_keys_map == NULL) {
virtual_keys_map_init(&virtual_keys_map);
}
if(modifier_flags_map == NULL) {
modifier_flags_map_init(&modifier_flags_map);
}
因为这似乎是一个图书馆,你有几种选择:
-
你可以让你的库更“面向对象”和力用户做正确的实例。例如,你有你的ADT struct defined为
KeyboardHandler
,然后你handle_keyboard_input
会是这个样子,而不是:void KH_handle_input(KeyboardHandler self, char **tokens, size_t num_tokens);
这意味着呼叫者现在是负责做这单件的实例:
// caller must get the ADT instance at some point, and you don't care when KeyboardHandler kh = KH_init(); KH_handle_input(kh, some_tokens, num_tokens); // some other part can be initialized later MouseHandler mh = MH_init(); MH_handle_input(mh, some_tokens, num_tokens);
-
可以为both Windows and POSIX dll创建库初始值设定项。所以你可以让它自动完成。如果你的函数想要使用这个可能未初始化的哈希表(或许它是一个单一的函数,但无论如何),似乎你将不得不做出这个“检查”。在这种情况下,我至少会重构它到一个单独的功能:
void handle_keyboard_input(char **tokens, size_t num_tokens) { initialize_hashes_if_needed(); // ...and then the rest of the function }
的原因是你不希望有修改几个功能,如果你决定有别的东西,需要被malloced。
函数中的静态(指针)变量也是单例。或者,甚至更简单一个全局变量。 – wildplasser
所以我可以像我的更新部分中使用这样的代码? –
启动时分配这些结构有什么问题?在调用每个单独的函数之前,我没有意义检查NULL。如果您想自动执行此操作,dll库也可以公开init函数。 – Groo