gpt4 book ai didi

c - C中文本查找的通用枚举

转载 作者:太空狗 更新时间:2023-10-29 16:00:58 27 4
gpt4 key购买 nike

[更新]

  1. 给出的代码确实有效。当我认为它没有时,我错了。我的错;对不起++。如果您可以改进代码,请在 https://codereview.stackexchange.com/questions/150480/generic-enum-to-text-lookup-in-c 进行改进
  2. 我们必须在编译时声明我们的字符串。我们编写嵌入式系统代码,不允许 malloc()。抱歉没说清楚。

[Update++] 我可能会接受以下答案之一。不过,我忘了说明,我们的枚举是不连续的,范围很广,这可能会有所不同


intertubes 和这个网站上充斥着要求从枚举中获取文本的问题。

我找不到一种规范的方法来做到这一点(并且会接受一个作为这个问题的答案),所以让我们看看我们是否可以在我们之间拼凑一个。

在我们的代码中,我们有多个结构数组,包含成对的枚举和相应的字符串。

问题在于字符串的长度不同,因此我们为每个字符串编写了一个查找函数,该函数在结构数组上循环,尝试匹配枚举并在找到匹配项时返回相应的文本。

让我们举以下两个人为的例子:

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=
typedef enum
{
north,
south,
east,
west
} E_directions;

struct direction_datum
{
E_directions direction;
char direction_name[6];
};

struct direction_datum direction_data[] =
{
{north, "north"},
{south, "south"},
{east, "east"},
{west, "west"},
};

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=
typedef enum
{
hearts,
spades,
diamonds,
clubs,
} E_suits;

struct suit_datum
{
E_suits suit;
char suit_name[9];
};

struct suit_datum suit_data[] =
{
{hearts, "hearts"},
{spades, "spades"},
{diamonds, "diamonds",},
{clubs, "clubs"},
};

除了字符串长度外,它们相似/相同,因此,理论上,我们应该能够编写一个通用函数来循环遍历 direction_datasuit_data ,给定一个索引并返回相应的文本。

我在想这样的事情——但它不起作用(结构中的枚举值似乎总是 zer0,所以很明显我的指针算法是关闭的)。

我做错了什么?

char *Get_text_from_enum(int enum_value, 
void *array,
unsigned int array_length,
unsigned int size_of_array_entry)
{
unsigned int i;
unsigned int offset;

for (i = 0; i < array_length; i++)
{
offset = i * size_of_array_entry;

if ((int) * ((int *) (array+ offset)) == enum_value)
return (char *) (array + offset + sizeof(int));
}

return NULL;
}


printf("Expect south, got %s\n",
Get_text_from_enum(south,
direction_data,
ARRAY_LENGTH(direction_data),
sizeof(direction_data[0])));

printf("Expect diamonds, got %s\n",
Get_text_from_enum(diamonds,
suit_data,
ARRAY_LENGTH(suit_data),
sizeof(suit_data[0])));

最佳答案

有两种“规范”的方法可以做到这一点。一种是可读的,另一种是避免代码重复的。


可读性

“可读方式”是我推荐的方式。它使用相应的查找表构建枚举,其中枚举常量与查找表索引匹配:

typedef enum
{
north,
south,
east,
west,
directions_n // only used to keep track of the amount of enum constants
} direction_t;

const char* STR_DIRECTION [] = // let array size be based on number of items
{
"north",
"south",
"east",
"west"
};


#define ARRAY_ITEMS(array) (sizeof(array) / sizeof(*array))
...
// verify integrity of enum and look-up table both:
_Static_assert(directions_n == ARRAY_ITEMS(STR_DIRECTION),
"direction_t does not match STR_DIRECTION");

如果你愿意,你仍然可以有一个基于此的结构:

typedef struct
{
direction_t dir;
const char* str;
} dir_struct_t;

const dir_struct_t DIRS [directions_n] =
{ // use designated initializers to guarantee data integrity even if item order is changed:
[north] = {north, STR_DIRECTION[north]},
[south] = {south, STR_DIRECTION[south]},
[east] = {east, STR_DIRECTION[east]},
[west] = {west, STR_DIRECTION[west]}
};

没有代码重复方式

另一种选择是使用所谓的“X-macros”,除非作为最后的手段,否则不推荐使用,因为它们往往会使代码严重不可读,特别是对于那些不使用此类宏的人.

此代码等同于我上面的示例:

#define DIRECTION_LIST \
X(north), \
X(south), \
X(east), \
X(west), // trailing commma important here! (and ok in enums since C99)

typedef enum
{
#define X(dir) dir
DIRECTION_LIST
#undef X
directions_n // only used to keep track of the amount of enum constants
} direction_t;

typedef struct
{
direction_t dir;
const char* str;
} dir_struct_t;

const dir_struct_t DIRS [directions_n] =
{
#define X(dir) {dir, #dir}
DIRECTION_LIST
#undef X
};

这个宏版本摆脱了显式字符串查找表。

关于c - C中文本查找的通用枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41259648/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com