c/c++语言开发共享在C中进行文本查找的通用枚举

[更新]


[更新++]我可能会接受下面的答案之一。 然而,我忘了说,我们的枚举是不连续的,并且范围很广,这可以有所作为


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"}, }; 

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

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

我做错了什么?

 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 %sn", Get_text_from_enum(south, direction_data, ARRAY_LENGTH(direction_data), sizeof(direction_data[0]))); printf("Expect diamonds, got %sn", Get_text_from_enum(diamonds, suit_data, ARRAY_LENGTH(suit_data), sizeof(suit_data[0]))); 

    我总是使用下面描述的方法。 请注意,所有枚举的数据结构和function都相同。

     struct enum_datum { int enum_val; char *enum_name; }; char *GetEnumName(enum_datum *table, int value) { while (table->enum_name != NULL) { if (table->enum_val == value) return enum_name; table++; } return NULL; } 

    在此之后,您需要定义每个特定的枚举:

     typedef enum { north, south, east, west } E_directions; enum_datum E_directions_datum[] = { { north, "north" }, { south, "south" }, { east, "east" }, { west, "west" }, { some_value_not_important, NULL }, // The end of the array marker. }; char *GetDirectionName(E_directions dir) { return GetEnumName(E_directions_datum, dir); } 

    请注意,该字符串可能与枚举器的名称不完全相同。 在我自己的项目中,有时我会为同一枚举创建几个enum_datum数组。 这样可以获得越来越详细的消息,而不会使整体设计变得非常复杂。

    而且几乎就是这样。 主要优点是简单。

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


    可读的方式

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

     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++开发分享在C中进行文本查找的通用枚举相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/559758.html

      (0)
      上一篇 2021年1月27日
      下一篇 2021年1月27日

      精彩推荐