【问题标题】:Key Value Pair in C LanguageC语言中的键值对
【发布时间】:2017-06-05 11:55:07
【问题描述】:

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

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

struct key_value kv;

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

但我不知道如何从这个结构中访问这些值。有人能解释一下吗?

【问题讨论】:

  • struct key_value kv;kv.keykv.value 之后将是左值。
  • 不清楚你在这里问什么 - 你知道结构在 C 中是如何工作的吗?
  • 我必须存储 30 个键/值对。访问该结构的逻辑应该是什么?
  • 您可以将它们放入结构数组[30] 中。然后使用键值,搜索具有匹配键的结构并读/写其值。
  • @Yunnosch 你能分享一下代码 sn-p 吗?

标签: c struct


【解决方案1】:

这是一个例子:

#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;
}

【讨论】:

    【解决方案2】:

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

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

    你需要一些东西来代表这个系列;暂时称它为ListMap

    struct ListMap;
    

    以上称为不完全类型。目前,我们并不关心其中的内容。除了将指针传递给周围的实例之外,您无法做任何事情。

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

    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.
    

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

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

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

    struct ListMap* newListMap();
    

    然后扔掉:

    void freeListMap(struct ListMap* listMap);
    

    难点在于实现这些功能如何完成它们的工作。无论如何,以下是您将如何使用它们:

    struct ListMap* myMap = newListMap();
    listMapInsert(myMap, 1, "foo");
    listMapInsert(myMap, 1729, "taxi");
    listMapInsert(myMap, 28, "perfect");
    
    char* value = listMapValueForKey(myMap, 28); // perfect
    freeListMap(myMap);
    

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

    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);
    }
    

    【讨论】:

      【解决方案3】:
      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";
      

      您将需要创建 N 次结构,并按照第一次的方式为它们赋值。或者创建具有 N 个结构的数组并通过循环对其进行迭代赋值。

      数组:

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

      【讨论】:

      • 是的,使用数组比创建任意数量的独立structs 要好得多,这些structs 除了名称之外没有任何关系,这对编译器无关紧要。这将是一个更好的例子。
      • 是的,同意刚刚添加。我在想他将从了解他可以创建多个结构中获得价值。他提出问题的方式我非常怀疑他是否知道结构是什么。
      【解决方案4】:

      您正在寻找的功能需要您自己在 C 中实现;例如您的结构类型的数组。
      下面是一个示例,说明如何读取键的值,而无需知道在哪个数组索引处可以找到该键。
      为了说明这一点,我将键编号向后。

      请注意,对于不存在的密钥等特殊情况,需要更复杂的 API 定义;为了方便起见,我只是盲目地返回最后一个条目。

      #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;
      }
      

      【讨论】:

        【解决方案5】:

        “我必须存储 30 个键/值对”

        创建一个struct 数组,例如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);
        

        您可以循环以将值分配给键和值。 访问kv 中的任何内容都很简单。

        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;
        

        【讨论】:

          【解决方案6】:

          您的代码已经拥有访问这些值的方法。

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

          获取分配的值很简单

          kv.key
          kv.value
          

          这是一个简单的结构,如果你想要类似 python dict 的东西,你需要实现一个哈希结构,这会更复杂。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多