在C中使用hashmap存储String - 整数映射一次并用于整个程序运行

时间:2017-08-20 15:02:43

标签: c static hashmap

我有自己的 C hash_map_t struct 的实现,我可以使用如下?

// 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 ++中,我可以创建一些Singleton模式或静态成员,但这种概念在C语言中不可用。可能我可以在程序开始的某个地方的程序启动时创建这个hash_map但是我怎样才能将引用传递给程序使用的库。

我最近的想法是使用static hash_map_t variable inside my handle_keyboard_input function并且仅在它为NULL(第一个函数调用)时以某种方式初始化它,并且如果在连续调用中变量不是NULL,则只重用先前初始化的hash_map_t结构。

解决这个问题的最佳方法是什么?

更新

我可以使用这样的代码吗?

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);
}

2 个答案:

答案 0 :(得分:1)

由于这似乎是一个库,因此您有以下几种选择:

  1. 您可以使您的库更“面向对象”并强制用户进行正确的实例化。例如,您将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);
    
  2. 可以为both Windows and POSIX dll创建库初始值设定项。所以你可以自动完成这项工作。

  3. 否则,在您的函数想要使用这个可能未初始化的哈希表时,您似乎必须进行“检查”(可能它是单个函数,但无论如何)。在这种情况下,我至少会将它重构为一个单独的函数:

    void handle_keyboard_input(char **tokens, size_t num_tokens) {
        initialize_hashes_if_needed();
        // ...and then the rest of the function            
    }
    

    理由是如果您认为还有其他东西需要进行malloced,您不希望修改多个功能。

答案 1 :(得分:0)

是的,上面的代码会导致指针只被初始化一次(或者如果你将它们设置为NULL,条件将是true并且它将再次初始化)并保留在内存中即使你得到功能之外。

函数static变量的生命周期在程序流第一次遇到声明时开始,并在程序终止时结束 - 换句话说,它们是全局变量。

此变量的名称只能在函数中访问,并且没有链接。

如果您认为需要全局可访问的变量,仍需要非常小心。 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);
}