2009-03-31 4 views
3

Я использую реализацию таблицы хэш-таблицы GLib в программе C и только сейчас Я просто экспериментирую с ней. Я написал следующий фрагмент кода для тестирования:Задача столбика столбика GLib

#include <glib.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <string.h> 

int main(){ 
// Some codes and declerations here 
GHashTable *g_hash_table; 
uint32_t *a; 
a=(uint32_t *)malloc(sizeof(uint32_t)); 
if(a==NULL){ 
    printf("Not Enough Mem For a\n"); 
    return 1; 
} 
*a=1123231; 

uint32_t* key; 
key=(uint32_t *)malloc(sizeof(uint32_t)); 
if(key==NULL){ 
    printf("Not Enough Mem For key\n"); 
    return 1; 
} 
*key=122312312; 
int i; 
g_hash_table=g_hash_table_new(g_int_hash, g_int_equal); 
for(i=0;i<TABLE_SIZE;i++){ 
    *key+=1; 
    *a+=1; 
    g_hash_table_insert(g_hash_table,(gpointer)key,(gpointer)a); 
    uint32_t *x=(uint32_t *)g_hash_table_lookup(g_hash_table,key); 
    printf("Counter:%d, %u\n",i,*x); 
} 

GHashTableIter iter; 
g_hash_table_iter_init(&iter,g_hash_table); 
int size=g_hash_table_size(g_hash_table); 
printf("First size: %d\n",size); 
uint32_t *val; 
uint32_t *key_; 
int counter=0; 

// My problem is in the following loop it 
// always returns the same and the last key value pair 
while(g_hash_table_iter_next(&iter,(gpointer*)(void*)&key_,(gpointer*)(void*)&val)){ 
    counter++; 
    printf("%u %u\n",(uint32_t)*key_,(uint32_t)*val); 
    printf("Counter: %d\n",counter); 
} 
//Some more code here   
    return 0; 
} 

Как-то мой тест код перебирает правильно, но в цикле она всегда возвращает последние пары ключей и последнее значение, и это всегда то же самое. В чем проблема? Вышеприведенный код может не работать с его форматом. Я только что скопировал и вложил некоторые части, чтобы дать четкое представление о том, что я пытаюсь сделать.

ответ

4

В сообщениях key, a есть ошибки. Вы всегда помещаете тот же указатель в хэш-таблицу. Попытка:

#include <glib.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <string.h> 

#define TABLE_SIZE 12 

int main() { 
    // Some codes and declarations here 
    GHashTable *g_hash_table; 
    int i; 

    g_hash_table = g_hash_table_new(g_int_hash, g_int_equal); 
    for (i=0; i<TABLE_SIZE; i++) 
    { 
     uint32_t* key = (uint32_t *)malloc(sizeof(uint32_t)); 
     uint32_t* a = (uint32_t *)malloc(sizeof(uint32_t)); 
     *key = i; 
     *a = i+10; 
     g_hash_table_insert(g_hash_table, (gpointer)key, (gpointer)a); 
     uint32_t *x = (uint32_t *)g_hash_table_lookup(g_hash_table,key); 
     printf("key: %d --> %u\n", *key ,*x); 
    } 

    GHashTableIter iter; 
    int size=g_hash_table_size(g_hash_table); 
    printf("First size: %d\n", size); 

    uint32_t *val; 
    uint32_t *key_; 

    // My problem is in the following loop 
    // it always returns the same and the last key value pair 

    g_hash_table_iter_init (&iter, g_hash_table); 
    while (g_hash_table_iter_next (&iter, (gpointer) &key_, (gpointer) &val)) 
    { 
     printf("key %u ---> %u\n", (uint32_t)*key_, (uint32_t)*val); 
    } 

    // TODO: free keys 
    return 0; 
} 
9

Я думаю, что ваш код вставки сломан. Вы выделяете память только один раз, но затем выполняете множество вложений, увеличивая значение, хранящееся в одном выделенном месте между ними.

Хэш-таблица хранит ваш указатель, поэтому он будет ассоциировать каждую клавишу с тем же указателем.

Кроме того, вы должны, вероятно, использовать g_malloc() с glib, для согласованности.

И я всегда рекомендую использовать sizeof на объектах, а не на их типах; таким образом вы не повторяете себя так же опасно. Таким образом, вместо

guint32 *a; 

    a = g_malloc(sizeof (guint32)); 

использования

a = g_malloc(sizeof *a); 

Таким образом, вы «заблокировать» зависимость, так что вы всегда выделить достаточно места, чтобы хранить любые a точки в, даже если впоследствии изменить тип ,

Далее вы должны внимательно изучить каждый сделанный вами бросок. Кастинг любого непостоянного указателя на gpointer является признаком нерешительного программиста. С glib, gpointer является просто синонимом void *, так что литье никогда не нужно. Это просто добавляет к вашему коду жесткость, что затрудняет чтение.

+0

Тонко вы были быстры: D. – systemsfault

+1

Грамматика для sizeof (C99 6.5.3) является 'sizeof унар-выражения | sizeof (type-name) ', и единственное использование в этом примере - это имя типа, поэтому здесь требуются парсеры. –

+0

Я использовал glib в течение долгого времени, это помогает в таких вещах. :) – unwind

Смежные вопросы