![](/img/trans.png)
[英]In bison is there a way to return the Name of a token instead of its type
[英]return enum's name instead of its value
我在枚舉中有一組值。 作為一個例子,我選擇了WEEK_DAY
(我的實際案例有很多(50+)個值,它們不是連續的( 1000,1001,2000,...
)):
typedef enum{
SUNDAY,
MONDAY,
FRIDAY = 6
}WEEK_DAY;
我現在想要創建一個函數,給定WEEK_DAY
值,它將返回其名稱。 我這樣做是通過使用:
#define STRING_REPLACE(x) #x
char *value_2_name(WEEK_DAY day)
{
switch(day)
{
case SUNDAY:
return STRING_REPLACE(SUNDAY);
case MONDAY:
return STRING_REPLACE(MONDAY);
case FRIDAY:
return STRING_REPLACE(FRIDAY);
}
}
並使用printf("%s", value_2_name(6));
調用它printf("%s", value_2_name(6));
/ printf("%s", value_2_name(FRIDAY));
將按預期打印出“星期五”。
有沒有辦法將此功能壓縮成一行?
即以某種方式在參數WEEK_DAY day
它的enum WEEK_DAY
對應物之間進行替換,然后使用STRING_REPLACE
?
我正在尋找的是: STRING_REPLACE(day_2_WEEK_DAY_enum
)
一些枚舉有強制值,所以不可能使用如何將枚舉名稱轉換為c中的字符串的答案
不是一行,但你可以使用符合標准的C編譯器(C99 +)和X宏 :
#define STRINGIFY(x) #x
#define WEEKDAYS \
X(SUNDAY,) \
X(MONDAY,) \
X(FRIDAY, = 6)
typedef enum {
#define X(name, init) name init,
WEEKDAYS
#undef X
} Weekday;
char *weekday_lookup[] = {
#define X(name, init) [name] = STRINGIFY(name),
WEEKDAYS
#undef X
};
這將機械地產生以下代碼:
typedef enum {
SUNDAY , MONDAY , FRIDAY = 6,
} Weekday;
char *weekday_lookup[] = {
[SUNDAY] = "SUNDAY", [MONDAY] = "MONDAY", [FRIDAY] = "FRIDAY",
};
另一種方法是,如果查找表變得太大或不可編譯(索引或負值太大),或者需要C89,則構建一個值表,將重復使用名稱對。
如果您不喜歡編寫反斜杠或長#define
,則可以使用包含X文件數據庫的文件:
weekday_def.inc :
X(SUNDAY,)
X(MONDAY,)
X(FRIDAY, = 6)
實際使用:
typedef enum {
#define X(name, init) name init,
#include "weekday_def.inc"
#undef X
} Weekday;
char *weekday_lookup[] = {
#define X(name, init) [name] = STRINGIFY(name),
#include "weekday_def.inc"
#undef X
};
你的解決方案非常好,因為它很簡單。 我想問題是當枚舉變得非常大時。 除了調用函數之外,我認為沒有辦法在一行中執行此操作。 正如'某些程序員老兄'所說,C沒有內省特征。 所以你必須自己做好准備。 我做了一個枚舉結構來做到這一點。 它將與枚舉中的間距一起工作 - 但是你可能會發現它變得多么復雜和荒謬,只是為了執行這個功能。
enum.h
#ifndef __ENUM_H__
#define __ENUM_H__
#define null 0x00
#define ENUM_MAX_VALUES 4
#define ENUM_MAX_SCHEMA 4
#define ENUM_MAX_ENUM 4
#define ENUM_MAX_STRING_LEN 16
/**
* enum_key_value_t is essentially a key/value pair
* the key is the integer, the value is the string
*/
typedef struct
{
/** integer enum value */
int key;
/** string enum value */
char value[ENUM_MAX_STRING_LEN];
}enum_key_value_t;
/**
* An enum schema contains all possible string/int pairs
*/
typedef struct
{
/** all possible values of the enumerator object */
enum_key_value_t values[ENUM_MAX_VALUES];
/** the number of values used out of MAX_ENUM_VALUES */
int num_values;
}enum_schema_t;
typedef struct
{
/** current value of the enumerator object */
enum_key_value_t *value;
enum_schema_t *schema;
}enum_t;
enum_schema_t *new_EnumSchema(void);
void EnumSchema_AddValue(enum_schema_t *e, int key, const char *value);
enum_key_value_t *Enum_SetValue(enum_t *e, int key);
const char *Enum_GetValue(enum_t *e);
enum_t *new_Enum(enum_schema_t *schema, int initial_value);
#endif
enum.c
#include "enum.h"
#include <string.h>
#include <stdio.h>
/** used in place of null strings etc. */
const char g_UNDEFINED[] = "<<UNDEFINED>>";
/** All enumerator objects */
static enum_schema_t g_EnumSchemas[ENUM_MAX_SCHEMA];
static enum_t g_Enums[ENUM_MAX_ENUM];
/** Current number of enumerator objects */
static int g_num_EnumSchemas = 0;
static int g_num_Enums = 0;
static enum_key_value_t *Enum_FindValue(enum_schema_t *e, int key);
/**
* new_Enum
*
* create a new enumerator
*
* @return pointer to the new enumerator
*/
enum_schema_t *new_EnumSchema(void)
{
if (g_num_EnumSchemas < ENUM_MAX_SCHEMA)
{
enum_schema_t *ret = &g_EnumSchemas[g_num_EnumSchemas++];
ret->num_values = 0;
return ret;
}
return null;
}
/**
* new_Enum
*
* create a new enumerator
*
* @return pointer to the new enumerator
*/
enum_t *new_Enum(enum_schema_t *schema, int initial_value)
{
if (g_num_Enums < ENUM_MAX_ENUM)
{
enum_t *ret = &g_Enums[g_num_Enums++];
ret->schema = schema;
ret->value = Enum_FindValue(schema, initial_value);
return ret;
}
return null;
}
/**
* Enum_AddValue
*
* adds a value/key key to a enumerator object
*
* @param e pointer to the enumerator object
* @param key the enumerated byte key
* @param value the value to show for this key
*/
void EnumSchema_AddValue(enum_schema_t *e, int key, const char *value)
{
if (e->num_values < ENUM_MAX_VALUES)
{
int i;
enum_key_value_t *val = &e->values[e->num_values++];
val->key = key;
strncpy(val->value, value, ENUM_MAX_STRING_LEN - 1);
val->value[ENUM_MAX_STRING_LEN - 1] = 0;
}
}
/**
* Enum_SetValue
*
* changes the enumerated key
*
* @param e pointer to the enumerator object
* @param key the new enumerated byte key
* @return pointer to the enum_key_value_t object that contains the key
*/
enum_key_value_t *Enum_SetValue(enum_t *e, int key)
{
enum_key_value_t *val = Enum_FindValue(e->schema, key);
if (val != null)
{
e->value = val;
return val;
}
return null;
}
/**
* Enum_GetValue
*
* gets the enumerated value key for enumerated key
*
* @param e pointer to the enumerator object
* @return value key
*/
const char *Enum_GetValue(enum_t *e)
{
if (e->value != null)
return e->value->value;
return g_UNDEFINED;
}
/*************************************
* STATIC FUNCTIONS (Local functions)
*************************************/
/**
* Enum_FindValue
*
* finds the enumerated key
*
* @param e pointer to the enumerator object
* @param key the enumerated byte key
* @return pointer to enum_key_value_t object that contains the key
*/
static enum_key_value_t *Enum_FindValue(enum_schema_t *e, int key)
{
int i;
for (i = 0; i < e->num_values; i++)
{
enum_key_value_t *val = &e->values[i];
if (val->key == key)
return val;
}
return null;
}
main.c中
#include <stdio.h>
#include "enum.h"
typedef enum
{
SUNDAY,
MONDAY,
FRIDAY = 6
}WEEK_DAY;
enum_schema_t *week_day_init()
{
enum_schema_t *enum_weekday = new_EnumSchema();
// add possible values
EnumSchema_AddValue(enum_weekday, SUNDAY, "SUNDAY");
EnumSchema_AddValue(enum_weekday, MONDAY, "MONDAY");
EnumSchema_AddValue(enum_weekday, FRIDAY, "FRIDAY");
return enum_weekday;
}
void main()
{
enum_schema_t *week_day_enum_t = week_day_init();
enum_t *weekday1 = new_Enum(week_day_enum_t, SUNDAY);
// the 'one-liner'
printf("weekday1 is currently '%s'\n",Enum_GetValue(weekday1));
Enum_SetValue(weekday1, FRIDAY);
printf("weekday1 is now '%s'\n", Enum_GetValue(weekday1));
}
產量
weekday1 is currently 'SUNDAY'
weekday1 is now 'FRIDAY'
丑陋,不可維護且效率不高,但完全符合您的要求:
#define ENUMS() \
ENTRY(SUNDAY, 0) \
ENTRY(MONDAY, 1) \
ENTRY(FRIDAY, 6)
typedef enum{
#define ENTRY(_enum, _val) _enum = _val,
ENUMS()
#undef ENTRY
}WEEK_DAY;
#define MAX_STR_LEN 7
char days_str[][MAX_STR_LEN]={
#define ENTRY(_enum, _val) #_enum,
ENUMS()
#undef ENTRY
};
char* value_2_name(WEEK_DAY day)
{
return days_str[day - ((1U - (((unsigned int)(day - sizeof(days_str)/MAX_STR_LEN))>>31))
*
(day - (sizeof(days_str)/MAX_STR_LEN) ) )
- (1U - (((unsigned int)(day - sizeof(days_str)/MAX_STR_LEN))>>31))] ;
}
它支持非連續的枚舉值,如圖所示,它使用最小的字符串數組 - 本例中的char*
數組大小為21個字節,只包含3個字符串, 沒有“漏洞” (計算數組索引的原因)但應該不被人類使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.