-1

I am very new in c language and I am so sorry if my question is too basic.

I want to define a dictionary in c in which I have a list as the value of my keys. In other word, I like to have something like this is python in c:

my_dictionary = {1:{'name':'john','items':['item1','item2']},2:{'name':'bob','items':['item3','item4']}}

Then I like to have access to my defined dictionary as this: my_item = my_dictionary[1]['items'].

I know this is very easy in python but for c, I could not find a good example for this. I am able to define simple dictionaries such as:

typedef struct dict_t_struct {
    char *key;
    void *value;
    struct dict_t_struct *next;
} dict_t;

and I can easily add, remove, or print items from this dictionary using below functions:

dict_t **dictAlloc(void) {
    return malloc(sizeof(dict_t));
}

void dictDealloc(dict_t **dict) {
    free(dict);
}

void *getItem(dict_t *dict, char *key) {
    dict_t *ptr;
    for (ptr = dict; ptr != NULL; ptr = ptr->next) {
        if (strcmp(ptr->key, key) == 0) {
            return ptr->value;
        }
    }

    return NULL;
}

void delItem(dict_t **dict, char *key) {
    dict_t *ptr, *prev;
    for (ptr = *dict, prev = NULL; ptr != NULL; prev = ptr, ptr = ptr->next) {
        if (strcmp(ptr->key, key) == 0) {
            if (ptr->next != NULL) {
                if (prev == NULL) {
                    *dict = ptr->next;
                } else {
                    prev->next = ptr->next;
                }
            } else if (prev != NULL) {
                prev->next = NULL;
            } else {
                *dict = NULL;
            }

            free(ptr->key);
            free(ptr);

            return;
        }
    }

but the problem is that I need to have linked list as the values of my dictionary and an inner dictionary in my dictionary.

  • That's just a case of what you store in the value, isn't it? By the look of it (though you haven't shows us your put function) this should already just work, putting the link list and then storing a dictionary inside the list if that's suitable. You'll need a slightly more complicated way of reading the value than python, but it could still be one line assuming you're sure the indices you're looking up are good. – Rup Dec 27 '18 at 00:31
  • 1
    You're missing a `type` member in the structure. The purpose of a `type` member is to specify the type of the `value` member, which could be, for example, an `int *`, a `char *`, or a pointer to a dictionary. – user3386109 Dec 27 '18 at 00:31
  • But this would be so much easier in C++, almost as easy as the Python, if you can use C++ instead? – Rup Dec 27 '18 at 00:31
  • 1
    Side note: code you found (or wrote?) does not implement what is called "dictionary" in most languages/frameworks - usually "dictionary" means hash table with O(1) lookup by key - code shown in the post is just linked list... – Alexei Levenkov Dec 27 '18 at 00:34
  • I can not use c++. Can you please help me how can I define an inner dictionary in my defined dictionary and then also how can I access to my items? – Shahrooz Pooryousef Dec 27 '18 at 00:35
  • How do you add item to the list? What is the type of `void *value;` supposed to be? Why do you return a double pointer from dictAlloc? – KamilCuk Dec 27 '18 at 00:46
  • Hi Kamil, that is an example, can you define a hash table for this kind of dictionary defined in python in c? my_dictionary = {1:{'name':'john','items':['item1','item2']},2:{'name':'bob','items':['item3','item4']}} – Shahrooz Pooryousef Dec 27 '18 at 00:52
  • It's really your job to know the tool and decide what's the best abstraction for your problem. `void *value` is quite good, but you need `enum value_type_e { STRING, INT, .... };` and to write abstraction for all possible types. Look at [json-c](https://github.com/json-c/json-c/blob/master/json_object.h#L171) - it has accesses for all possible json values. I would settle with smth along `struct dict_s { char *key; void *value; enum dict_elem_type_e { DICT_ELEM_STRING, DICT_ELEM_OBJ, } type; }`. There is much of abstraction writing to be done. You can look at python C api. – KamilCuk Dec 27 '18 at 01:12
  • Here's an answer of mine that may help a bit: https://stackoverflow.com/questions/34777451/is-it-possible-to-do-inheritance-from-an-abstract-base-struct-or-simulate-someth/34781775#34781775 – Craig Estey Dec 27 '18 at 01:26

1 Answers1

2

1 Your structure is json, you can't use the normal dictionary completely

2 If you need to store a list, you need to define the data structure of the list.

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

#define DICT_STRING 1
#define DICT_LIST 2

typedef struct list_node {
    void* value;
    struct list_node* next;
} list_node;

typedef struct list {
    list_node* head;
} list;

typedef struct dict_entry {
    int type;
    char* key;
    void* value;
    struct dict_entry* next;
} dict_entry;

typedef struct dict_t {
    dict_entry* head;
} dict_t;

dict_t* dictAlloc(void) {
    dict_t* d = malloc(sizeof(dict_t));
    d->head = NULL;
    return d;
}

void dictDealloc(dict_t* dict) {
    free(dict);
}

dict_entry* addItem(dict_t* dict, int type, char* key, void* value) {
    dict_entry* de = malloc(sizeof(*de));
    de->type = type;
    de->key = key;
    de->value = value;
    de->next = dict->head;
    dict->head = de;
    return de;
}

dict_entry* getItem(dict_t* dict, char* key) {
    dict_entry* de = dict->head;
    while (de) {
        if (strcmp(de->key, key) == 0) {
            return de;
        }

        de = de->next;
    }

    return NULL;
}

int main(int argc, char** argv) {
    dict_t* d = dictAlloc();
    dict_entry* de;

    list* l = malloc(sizeof(*l));
    list_node* n = malloc(sizeof(*n));
    n->value = "value";
    l->head = n;

    addItem(d, DICT_LIST, "key", l);
    de = getItem(d, "key");
    switch (de->type) {
        case DICT_LIST: {
            list* l = de->value;
            printf("%s", l->head->value);
        }
    }
}
sundb
  • 490
  • 2
  • 8