Вставка общих значений в HashMap C

#arrays #c #pointers #generics #hashmap

#массивы #c #указатели #общие #hashmap

Вопрос:

У меня есть функция( create ) для создания hashmap.

Моя hashmap больше 11, но это пример, и я ищу, чтобы сделать код более понятным, насколько это возможно.

Хэш-карта будет содержать пару КЛЮЧ-ЗНАЧЕНИЕ в каждом узле. Моя цель — создать общую функцию вставки, в которую я могу вставлять int и char т. Д. Из массива.

В моем примере Insert функция insert Int принимает в качестве параметров Table t (куда я вставляю int то, что я создал ранее) два указателя на значения, которые я должен вставить, позицию, в которую я должен вставить значения в hashmap, и compare функцию, переданную пользователем, чтобы сравнить два ключа и вернуть 1, если они равны. Проблема в том, что когда я пытаюсь распечатать hashmap ( print(t) ), он возвращает в каждой позиции последнюю вставленную пару.

введите мои arr[11] и arr2[11]

ожидаемый результат

 key: 1,val: 11
key: 2,val: 10
key: 3,val: 9
key: 4,val: 8
key: 5,val: 7
key: 6,val: 6
key: 7,val: 5
key: 8,val: 4
key: 9,val: 3
key: 10,val: 2
key: 11,val: 1
 

реальный вывод

 key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
key: 11, val: 1
 

main.c

 int compare(void *key,void *key2){
    int k = *(int*)key;
    int k2 = *(int*)key2;
    if(k==k2){
        return 1;
    }else return 0;
}

int main(){

 struct table*t = create(11);
 int arr[11]={1,2,3,4,5,6,7,8,9,10,11};
 int arr2[11]={11,10,9,8,7,6,5,4,3,2,1};
    for(int p=0;p<11;p  ){
        int i = arr[p];
        int *key= amp;i;
        int i2 = arr2[p];
        int *value= amp;i2;
        insert(t,key,value,p, compare);
    }
 print(t);

 

function.c

 struct node{
    void* key;
    void* val;
    struct node *next;
    struct node *prev;
};

struct table{
    int size;
    struct node **list;
};

struct table *create(int size){
    struct table *t = (struct table*)malloc(sizeof(struct table));
    t->size = size;
    t->list = (struct node**)malloc(sizeof(struct node*)*size);
    int i;
    for(i=0;i<size;i  )
        t->list[i] = NULL;
    return t;
}

void insert(struct table *t,void* key,void* val,int pos, int(*comp)(void*, void*)){

    struct node *list = t->list[pos];
    struct node *newNode = (struct node*)malloc(sizeof(struct node));
    struct node *temp = list;
    while(temp){
        if(((*comp)(temp->key, key))==1){
            printf("%s", "key already create.");
            return;
        }
        temp = temp->next;
    }
    newNode->next = t->list[pos];
    newNode->key = key;
    newNode->val = val;
    if(list!=NULL){
        list->prev = newNode;
    }
    t->list[pos] = newNode;
    newNode->prev = NULL;
}

void print(struct table *t){
    for (int i = 0; i < t->size;   i) {
        struct node *list = t->list[i];
        while(list){
            if(list->key!=NULL) {
                printf("key: %d, val: %dn",*(int*)list->key, *(int*)list->val);
            }
            list = list->next;
        }
    }
}
 

Ответ №1:

вы передаете один и тот же адрес для всех значений и ключа здесь, поэтому к тому времени, когда вы дойдете до конца, последнее значение реплицируется во всех указателях

 int i = arr[p];
int *key= amp;i;
int i2 = arr2[p];
int *value= amp;i2;
 

вместо этого вы можете скопировать количество байтов из местоположения, как показано ниже.

 //newNode->key = key;
newNode->key = malloc(sizeof(int));
memcpy(newNode->key, key,sizeof(int) );
//newNode->val = val;
newNode->val = malloc(sizeof(int));
memcpy(newNode->val, val,sizeof(int) );

 

ПРИМЕЧАНИЕ: после выполнения вам придется обрабатывать проверки ошибок malloc и free памяти.

Ответ №2:

проблема возникла из функции main.

 int i = arr[p];
int *key= amp;i;
 

Ваш ключ является указателем на переменную i, а не на значение в arr.

Правильный путь:

 int * key = amp;arr[p];
 

(та же проблема для значения)