我需要将值转换为人类可读的字符串。通常对于 I 定义的东西,我会使用从零开始的值,并创建一个简单的字符串数组,其值为索引。
static const char *foo[] = { "foo", "bar", "etc" };
if (val < 3) printf("%s\n", foo[val]);
对于这种情况,我的值不是从0开始,它们之间存在一些差距。有没有一个很好的方法来做到这一点,而不必手动编码索引的一堆空字符串没有匹配的值/字符串对?
static const char *foo[] = { "", "", "", "foo", "", "bar", "", "", "etc" };
答案 0 :(得分:7)
从C99开始,您可以使用designated initialisers:
static const char *foo[] = {
[3] = "foo",
[5] = "bar",
[8] = "etc"
};
这相当于您发布的数组定义,并将生成包含9个条目的数组。结构体的初始化有类似的语法:
struct Person joe = {
.name = "Joe", .age = 24, .favcolor = "mauve"
};
请注意,这只是一个C功能和will not work in C++。
答案 1 :(得分:3)
如果没有太多间隙,您可以将每个连续序列编码为单独的数组,然后进行一些边界检查以找到要使用的合适序列。这是一个快速而肮脏的例子:
#include <stdio.h>
#include <stdlib.h>
static const int array_first_indices[] = {3, 15, 28, 32};
static const char * array0[] = {"foo"};
static const char * array1[] = {"bar", "baz"};
static const char * array2[] = {"bloop", "blorp", "blat"};
static const char * array3[] = {"glop", "slop", "bop"};
#define check_array(whichArray, idx) { \
unsigned int relIdx = idx - array_first_indices[whichArray]; \
if (relIdx < (sizeof(array##whichArray)/sizeof(const char *))) \
return array##whichArray[relIdx]; \
}
const char * LookupWord(int idx)
{
check_array(0, idx);
check_array(1, idx);
check_array(2, idx);
check_array(3, idx);
return NULL;
}
int main(int args, char ** argv)
{
for (int i=0; i<50; i++) printf(" LookupWord(%i) = %s\n", i, LookupWord(i));
return 0;
}
对于完全通用的查找机制,您可能需要使用像哈希表或树这样的数据结构;这些数据结构的C实现是可用的,但如果您可以选择使用C ++,那么使用该语言的数据结构会更容易,因为它们是由标准库提供的。
答案 2 :(得分:1)
创建一个将ID映射到字符串的排序数组,并使用bsearch()
函数查找字符串:
#include <stdio.h>
#include <stdlib.h>
struct id_msg_map {
int id;
char const* str;
};
int comp_id_string( const void* key, const void* element)
{
int key_id = ((struct id_msg_map*) key)->id;
int element_id = ((struct id_msg_map*) element)->id;
if (key_id < element_id) return -1;
if (key_id > element_id) return 1;
return 0;
}
static struct id_msg_map msg_map[] = {
{3, "message 3"} ,
{12, "message 12"},
{100, "message 100"},
{32000, "message 32000"},
};
#define ELEMENTS_OF(x) (sizeof(x) / sizeof((x)[0]))
char const* get_msg(int x)
{
struct id_msg_map key = {x};
struct id_msg_map* msg = bsearch(&key, msg_map, ELEMENTS_OF(msg_map), sizeof(msg_map[0]), comp_id_string);
if (!msg) return "invalid msg id";
return msg->str;
}
void test_msg(int x)
{
printf("The message for ID %d: \"%s\"\n", x, get_msg(x));
}
int main(void)
{
test_msg(0);
test_msg(3);
test_msg(100);
test_msg(-12);
return 0;
}
答案 3 :(得分:0)
你可以使用指定的初始化工具,如M. Oehm's post中所述,但是这会默默地引入您之前提到的相同差距(隐式0
值)。当您知道0
永远不会是实际选择,表格没有动态变化(特别是大小)以及表格的大小很小时,该选项最合适。
如果表格特别大,但从未添加或删除项目,则可以在键/值对样式结构上使用qsort
和bsearch
。例如:
struct foo_pair {
int key;
char *value;
};
int foo_pair_compare(void *x, void *y) {
struct foo_pair *a = x, *b = y;
return (a->key > b->key) - (a->key < b->key);
}
int main(void) {
struct foo_pair foo[] = { { .key = 3, .value = "foo" },
{ .key = 5, .value = "bar" },
{ .key = 6, .value = "etc" } };
/* qsort needs to be done at the start of the program,
and again each time foo changes */
qsort(foo, sizeof foo / sizeof *foo, sizeof *foo, foo_pair_compare);
/* bsearch is used to retrieve an item from the sorted array */
struct foo_pair *selection = bsearch(&(struct foo_pair) { .key = 5 },
foo, sizeof foo / sizeof *foo,
sizeof *foo, foo_pair_compare);
}
当从集合中例行添加或删除项目时,选择哈希表或某种有序映射会更有意义。如果你不能在编写和测试你自己的这些系列时感到困扰,我想有很多尝试过的&amp;您可以在互联网上测试图书馆。