从int到const string的习惯C映射



我如何用C语言表达像这样的地图?

{
{1, "One"},
{1000, "One thousand"},
{1000000, "One million"}
}

键是int型,可以是大int型,值是一个常量字符串,并且在编译时已知。

地图将包含大约20或30个元素。

我会写这个函数:

const char* numbers( const int i ) 
{
   switch( i ) {
      case       1: return "One";
      case    1000: return "One thousand";
      case 1000000: return "One million";
      default: return "";
   }
}

有没有更好的(更习惯的)方法来做这件事?

使用开关是完全习惯的C语言,有一个单独的风格考虑(这将适用于几乎任何语言),您是否希望将键/值数据从程序逻辑中分离出来。

你可以使用const struct { int key; const char *value; };的数组,但你会开始担心是否应该使用线性搜索,二进制搜索,完全哈希等。有了开关,编译器就把它从你的手中拿走了。

如果你有某种关联容器(树或哈希映射),你可以在这个项目中使用其他东西,那么你可以使用它,但它真的不值得为30个项目的集合编写一个

就像你做的那样:

typedef struct {
    long long key;
    char *val;
} Item;
const Item mydict[] = {
    {1, "One"},
    {1000, "One thousand"},
    {1000000, "One million"}
};

我留下numbers()函数体作为练习。

Steve Jessop建议的替代解决方案也是完全有效的。

如果一切都是静态已知的,我会这样做:

char strings[][] = {"One", "One thousand", "One million", /* whatever */};
int map[] = {1, 1000, 1000000};
const char *numbers(const int i)
{
    position = search(map, i);// if the array is too small, just linear search
                              // if it is big, you can binary search
                              // if there is a relation use a formula
                              // although a formula is not extendable.
                              // In this case, it is log(i) in base 1000.
    return strings[position];
}

此方法可以扩展到非静态数据。您只需要确保正确填充strings数组并保持map排序。

注意:显然,您应该添加足够的错误检查等。例如在search找不到i的情况下

这可能是一个解决方案。

基本上是创建排序的键值对数组,然后使用bsearch-function(执行二进制搜索)快速找到正确的值。实现你自己的二进制搜索使搜索更方便可能是有意义的。

#include <stdlib.h>
#include <stdio.h>
typedef struct mapping
{
    int key;
    char* value;
} Mapping;
int mappingCompare(const void* a, const void* b)
{
    const Mapping* first = (const Mapping*)a;
    const Mapping* second = (const Mapping*)b;
    return second->key - first->key;
}
int main()
{
    Mapping map[3];
    Mapping search;
    Mapping* result;
    map[0].key = 1;
    map[0].value = "One";
    map[1].key = 1000;
    map[1].value = "One thousand";
    map[2].key = 1000000;
    map[2].value = "One million";
    //qsort is only needed if the map is not already in order
    qsort(map, 3, sizeof(Mapping), mappingCompare);
    search.key = 1000;
    result = (Mapping*)bsearch(&search, map, 3, sizeof(Mapping), mappingCompare);
    printf("value for key 1000 is %sn", result->value);
}

最新更新