如何在c中将值转换为枚举常量?

如何在c中将值转换为枚举常量?,c,enums,C,Enums,早些时候,我正在为我的解析器修复一个lexer;现在我必须为它创建一个验证程序。我的想法是使用以下预处理器宏将枚举常量转换为字符串:define macro\u STRINGIFYx 然后我做了一个函数来比较不同的令牌值,我做了三个,但它们都是相同的,只是有一些小的变化: unsigned int compare_keyword( enum script_keywords keyword, char *token ) { char *temporary = MACRO_STRINGIFY(

早些时候,我正在为我的解析器修复一个lexer;现在我必须为它创建一个验证程序。我的想法是使用以下预处理器宏将枚举常量转换为字符串:define macro\u STRINGIFYx

然后我做了一个函数来比较不同的令牌值,我做了三个,但它们都是相同的,只是有一些小的变化:

unsigned int compare_keyword( enum script_keywords keyword, char *token ) {
  char *temporary = MACRO_STRINGIFY( keyword );
  unsigned int i = 0;
  for (; i < (strlen( "KEYWORD_" ) + 1); i++) {
    ++temporary;
  }
  // 0 on match, 1 on no match
  return strcmp( temporary, token ) ? 1 : 0;
}
另一方面,如果我传递像1这样的值(符号枚举常量关键字_if解析为的值),则函数无法按预期工作:

// Same as last time with one edit:
void test() {
  /* See above code with following change on line 4 */
  compare_keyword( 1, "IF" ) /* etc... */
  /* Rest of code from previous test */
}
test(); //--> Outputs 'IF is not a keyword' even if KEYWORD_IF resolves to the value 1.
这里我要说的是,预处理器是非常文字化的,我更喜欢使用for循环有效地循环常量,而不会增加代码大小,如果我最终使用枚举常量,就会出现这种情况。因此,问题是如何在不使用switch…case…或if…else…的情况下将普通整数值转换为它们的符号名

编辑:枚举详细信息:


宏STRINGIFY在编译时由预处理器计算。它将返回参数的实际名称,因此

MACRO_STRINGIFY(keyword) -> "keyword"
MACRO_STRINGIFY(KEYWORD_IF) -> "KEYWORD_IF"
MACRO_STRINGIFY(1) -> "1"
显然,这不会导致任何解决办法

相反,可以使用编译时生成的键值映射来实现此类功能:

struct map
{
  int key;
  const char* value;
};

struct map mappings[] =
{
  { KEYWORD_IF, "IF" },
  { KEYWORD_ELSE, "ELSE" }
};
然后在运行时简单地迭代这些映射条目,以找出您需要的内容:

static int is_keyword(const char* str)
{
  int i;
  const int count = sizeof(mappings) / sizeof(mappings[0]);

  for(i = 0; i < count; i++)
  {
    struct map* m = &mappings[i];

    if(strcmp(str, m->value) == 0)
    {
      return 1;
    }
  }

  return 0;
}

void test()
{
  const char* str = "IF";
  const char* what;

  if(is_keyword(str))
  {
    what = "a keyword";
  }
  else
  {
    what = "not a keyword";
  }

  printf("%s is %s.\n", str, what);
}
这大概是最低限度的。可执行二进制文件通常不包括枚举值的名称,例如Java


为了进一步扩展这一点,您可以执行一些预处理器巫术来半自动地生成映射数组。但由于我不是预处理器巫毒的大朋友,我将跳过这一点

为什么你真的需要这种行为?通常,您会比较枚举值。如果我比较字符串,则不会;整数值对于字符串比较是无用的。什么函数工作得绝对好?宏字符串化关键字;将返回字符串关键字。它对您有什么帮助?您可能想查找x宏。在这方面有一些问题。枚举常量在编译程序中不存在;它们是一个源代码唯一的工件。不能直接从它们的int值生成它们的字符串表示形式。但是,您可以创建一个查找表,通过该表可以获取常量的字符串版本。请注意,当不同的常量对应相同的值时,这将是有损的,这确实可能发生,但默认情况下不会发生。无论如何,谢谢,但我决定使用字符串数组进行简单的查找表。没问题;这是一种更通用的方法,如果您打算重用关键字类型,那么这种方法很好。对于一个简单的查找来说,某个东西是关键字还是不在乎哪个,那么LUT显然就足够了。
struct map
{
  int key;
  const char* value;
};

struct map mappings[] =
{
  { KEYWORD_IF, "IF" },
  { KEYWORD_ELSE, "ELSE" }
};
static int is_keyword(const char* str)
{
  int i;
  const int count = sizeof(mappings) / sizeof(mappings[0]);

  for(i = 0; i < count; i++)
  {
    struct map* m = &mappings[i];

    if(strcmp(str, m->value) == 0)
    {
      return 1;
    }
  }

  return 0;
}

void test()
{
  const char* str = "IF";
  const char* what;

  if(is_keyword(str))
  {
    what = "a keyword";
  }
  else
  {
    what = "not a keyword";
  }

  printf("%s is %s.\n", str, what);
}