C语言中的键值对

Dev*_*per 4 c struct

我是 C 编程新手,我正在尝试创建一个像 Perl 编程一样的键值结构。我看到了一种解决方案,例如:-

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

struct key_value kv;

kv.key = 1;
kv.value = "foo";
Run Code Online (Sandbox Code Playgroud)

但我不知道如何从这个结构中访问这些值。有人可以阐明这一点吗?

Jer*_*myP 5

你缺少的是一个集合。大多数语言都有一种称为字典或映射或关联数组或其某些变体的数据类型。C没有这种类型的数据结构;事实上,C 中内置的唯一集合类型是数组。因此,如果您想要可以提供密钥并获取值的东西,您必须自己推出或在互联网上找到一个。后者可能更可取,因为如果您自己构建(特别是如果您是初学者),您可能会犯错误并产生缓慢的数据结构。

为了让您了解最终的结果,这里有一个简单的示例:

你需要一些东西来代表这个集合;ListMap暂时称其为:

struct ListMap;
Run Code Online (Sandbox Code Playgroud)

以上称为不完全类型。目前,我们不关心里面有什么。除了传递指向实例的指针之外,你不能用它做任何事情。

您需要一个函数来将项目插入到您的集合中。它的原型看起来像这样:

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.
Run Code Online (Sandbox Code Playgroud)

您需要一个函数来检索任何一个键的值。

const char* listMapValueForKey(struct ListMap* collection, int key);
Run Code Online (Sandbox Code Playgroud)

您还需要一个函数来初始化集合:

struct ListMap* newListMap();
Run Code Online (Sandbox Code Playgroud)

并把它扔掉:

void freeListMap(struct ListMap* listMap);
Run Code Online (Sandbox Code Playgroud)

难点在于实现这些函数如何完成它们的任务。无论如何,以下是您将如何使用它们:

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

char* value = listMapValueForKey(myMap, 28); // perfect
freeListMap(myMap);
Run Code Online (Sandbox Code Playgroud)

这是一个简单的实现。这只是为了说明,因为我还没有测试它,并且搜索条目随着条目数量线性增加(您可以比使用哈希表和其他结构做得更好)。

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);
}
Run Code Online (Sandbox Code Playgroud)