C语言中文本查找的通用枚举 [英] Generic enum to text lookup in C

查看:97
本文介绍了C语言中文本查找的通用枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[更新]

  1. 给出的代码确实有效.当我以为没有错的时候我就误会了.我的错;对不起++.如果您可以改进代码,请访问 https://codereview .stackexchange.com/questions/150480/generic-enum-to-text-lookup-in-c
  2. 我们 必须 在编译时声明我们的字符串.我们对嵌入式系统进行编码,并且不允许使用malloc().抱歉,不清楚.
  1. the code given does actually work. I was mistaken when I thought that it did not. My bad; sorry++. If you can improve the code, please do so at https://codereview.stackexchange.com/questions/150480/generic-enum-to-text-lookup-in-c
  2. We must declare our strings at compile time. We code embedded systems and are not allowed to malloc(). Sorry for not being so clear.


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


[Update++] I will probably accept one of the answers below. I forgot to state, though, that our enums are non-contiguous and have a wide range, which can make a difference

Intertube和这个站点充斥着一些问题,要求从枚举中获取文本.

The intertubes, and this site, are awash with questions asking for to get text from an enum.

我无法找到一种规范的方式来做到这一点(并且愿意接受一个答案),所以让我们看看是否可以在我们之间拼凑一个.

I cannot find a canonical way to do this (and would accept one as answer to this question), so let's see if we can cobble one together between us.

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

Throughout our code, we have multiple arrays of structures, containing pairs of enums and corresponding strings.

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

The problem is that the strings have different lengths, so we code a lookup function for each one, which for loops over an array of structures, trying to match the enum and returning the corresponding text if a match is found.

下面举两个人为设计的例子:

Let’s take the following two contrived examples:

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=
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,并给出索引并返回相应的文本.

Apart from the string length, they are similar/identical, so, in theory, we should be able to code a generic function to loop over either direction_data or suit_data, given an index and return the corresponding text.

我在想类似的事情–但它不起作用(该结构中的枚举值始终似乎为zer0,因此显然我的指针算法已关闭).

I am thinking something like this – but it doesn’t work (the enum value in the struct always seems to be zer0, so obviously my pointer arithmetic is off).

我做错了什么?

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])));

推荐答案

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

I always use the approach that is described below. Note that the data structure and the function are the same for all enums.

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

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

After that for each specific enum you need to define:

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数组.这样一来,即可获得越来越少的详细消息,而不会严重使总体设​​计复杂化.

Note that the string may not be exactly the same as the name of the enumerator. In my own projects sometimes I have several enum_datum arrays for the same enum. This allows getting more and less detailed messages without seriously complicating the overall design.

几乎就是这样.主要优点是简单.

And pretty much that is it. The major advantage is simplicity.

这篇关于C语言中文本查找的通用枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆