Developer
Developer

Reputation: 113

Key Value Pair in C Language

I am new to C programming and I am trying to create a key value structure as in Perl Programming. I saw one solution like :-

struct key_value
{
   int key;
   char* value;
};

struct key_value kv;

kv.key = 1;
kv.value = "foo";

But I don't know how to access these values from this structure. Can someone enlight on this ?

Upvotes: 4

Views: 29427

Answers (6)

ytobi
ytobi

Reputation: 673

"I have to store 30 key/value pair"

Create an array of struct e.g., key_value.

struct key_value
{
    int key;
    char* value;
};

struct key_value kv[30];

kv[0].key = 1;
kv[0].value = "foo";

printf("%s", kv[0].value);

You can loop through to assign values to keys and values. Access to whatever is in kv is simple.

int i = kv[0].key`;// copy value of k[0].key to i
char *v = kv[0].value; // copy value of k[0].value to v;

Upvotes: 1

JeremyP
JeremyP

Reputation: 86651

What you are missing is a collection. Most languages have a data type called a dictionary or a map or an associative array or some variation thereof. C does not have a data structure of this type; in fact, the only collection type you have built in to C is the array. So, if you want something where you can supply a key and get the value, you have to roll your own or find one on the Internet. The latter is probably preferable because you are likely to make mistakes and produce a slow data structure if you roll your own (especially if you are a beginner).

To give you a flavour of what you'll end up with, here's a simple example:

You'll need something to represent the collection; call it a ListMap for now:

struct ListMap;

The above is called an incomplete type. For now, we are not concerned with what's in it. You can't do anything with it except pass pointers to instances around.

You need a function to insert items into your collection. Its prototype would look something like this:

bool listMapInsert(struct ListMap* collection, int key, const char* value);
// Returns true if insert is successful, false if the map is full in some way.

And you need a function to retrieve the value for any one key.

const char* listMapValueForKey(struct ListMap* collection, int key);

You also need a function to initialise the collection:

struct ListMap* newListMap();

and to throw it away:

void freeListMap(struct ListMap* listMap);

The hard bit is implementing how those functions do what they do. Anyway, here's how you would use them:

struct ListMap* myMap = newListMap();
listMapInsert(myMap, 1, "foo");
listMapInsert(myMap, 1729, "taxi");
listMapInsert(myMap, 28, "perfect");

char* value = listMapValueForKey(myMap, 28); // perfect
freeListMap(myMap);

Here's a simple implementation. This is just for illustration because I haven't tested it and searching for entries increases linearly with the number of entries (you can do much better than that with hash tables and other structures).

enum
{
    listMapCapacity = 20
};
struct ListMap
{
    struct key_value kvPairs[listMapCapacity];
    size_t count;
};

struct ListMap* newListMap()
{
    struct ListMap* ret = calloc(1, sizeof *ret);
    ret->count = 0; // not strictly necessary because of calloc
    return ret;
}

bool listMapInsert(struct ListMap* collection, int key, const char* value)
{
    if (collection->count == listMapCapacity)
    {
        return false;
    }
    collection->kvPairs[count].key = key;
    collection->kvPairs[count].value = strdup(value);
    count++;
    return true;
}

const char* listMapValueForKey(struct ListMap* collection, int key)
{
    const char* ret = NULL;
    for (size_t i = 0 ; i < collection->count && ret == NULL ; ++i)
    {
        if (collection->kvPairs[i].key == key)
        {
            ret = kvPairs[i].value;
        }
    }
    return ret;
}

void freeListMap(struct ListMap* listMap)
{
    if (listMap == NULL)
    {
        return;
    }
    for (size_t i = 0 ; i < listMap->count ; ++i)
    {
        free(listMap->kvPair[i].value);
    }
    free(listMap);
}

Upvotes: 5

Yunnosch
Yunnosch

Reputation: 26703

The functionality you are looking for needs your own implementation in C; e.g. an array of your struct-type.
Here is an example of how to read the value for a key, without knowing anything about at which array-index the key will be found.
I have the keys numbered backward in order to illustrate that.

Note that more sophisticated API definitions are needed for special cases such as non-existing key; I just blindly return the last entry to keep things easy here.

#include <stdio.h>

#define MAPSIZE 30

struct key_value
{
   int key;
   char* value;
};

struct key_value kvmap[MAPSIZE];

void initmap(void)
{
    int i;
    for(i=0; i<MAPSIZE; i++)
    {
         kvmap[i].key=MAPSIZE-i-1;
         kvmap[i].value="unset";
    }

    kvmap[0].value="zero";
    kvmap[1].value="one";
    kvmap[2].value="two";
    kvmap[3].value="three";
    kvmap[4].value="four";
    kvmap[5].value="five";
    kvmap[6].value="six";
    kvmap[7].value="seven";
    kvmap[8].value="eight";
    kvmap[24].value="find this"; // it has the key "5"

}

char* readmap(int key)
{
    int i=0;
    while ((i<MAPSIZE-1) && (kvmap[i].key!=key))
    {   printf("Not in %d\n", i);
        ++i;}

    // will return last entry if key is not present
    return kvmap[i].value;
}

int main(void)
{
    initmap();

    printf("%s\n", readmap(5));
    return 0;
}

Upvotes: 1

du4ko
du4ko

Reputation: 101

typedef struct key_value
{
   int key;
   char* value;
}List;

struct key_value k1;
struct key_value k2;
struct key_value k3;

k1.key = 1;
k1.value = "foo";
k2.key = 2;
k2.value = "sec";
k3.key = 3;
k3.value = "third";

You will need to create N times the struct and give them values the way you did the first one. Or create array with N structs and iterate assign it values with a loop.

Array:

List arr[29];

int i;
for(i = 0;i<=28;i++){
    arr[i].key = i;
    arr[i].value = "W/e it needs to be";
}

Upvotes: 1

Overflow 404
Overflow 404

Reputation: 492

Here is an example:

#include <stdio.h>
#include <stdlib.h>
struct key_value
{
    int key;
    char* value;
};

int main(void)
{
    int number_of_keys = 2;
    struct key_value *kv = malloc(sizeof(struct key_value) * number_of_keys);
    if (kv == NULL) {
        perror("Malloc");
        exit(EXIT_FAILURE);
    }

    kv[0].key = 8;
    kv[0].value = "Test 8 key!";

    kv[1].key = 6;
    kv[1].value = "Test 6 key!";

    printf("Key = %d\nKey value = %s\n", kv[0].key, kv[0].value);
    printf("Key = %d\nKey value = %s\n", kv[1].key, kv[1].value);


    free(kv);
    return 0;
}

Upvotes: 4

Caio Belfort
Caio Belfort

Reputation: 555

Your code already have the method to acess the values.

kv.key = 1 
kv.value = "foo"

To get the values assigned is simple

kv.key
kv.value

It is a simple struct, if you wanna something like python dict you will need to implement a hash struct which will be more complicated.

Upvotes: 0

Related Questions