我如何用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);
}