c++ - ejemplo - Cómo obtener el nombre del elemento enum de su valor
typedef enum c (8)
Declaré un tipo de enumeración como este,
enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};
¿Cómo puedo obtener el nombre del elemento "Lun, Mar, etc." cuando ya tengo el valor del elemento "0, 1, etc."?
Ya tengo una función como esta
Log(Today is "2", enjoy! );
Y ahora quiero la salida abajo.
Hoy es miércoles, disfruta
¿Cómo puedo obtener el nombre del elemento "Lun, Mar, etc." cuando ya tengo el valor del elemento "0, 1, etc."?
En un código C más antiguo (hace bastante tiempo), encontré un código análogo a:
std::string weekEnumToStr(int n)
{
std::string s("unknown");
switch (n)
{
case 0: { s = "Mon"; } break;
case 1: { s = "Tue"; } break;
case 2: { s = "Wed"; } break;
case 3: { s = "Thu"; } break;
case 4: { s = "Fri"; } break;
case 5: { s = "Sat"; } break;
case 6: { s = "Sun"; } break;
}
return s;
}
Con: Esto establece una "dependencia patológica" entre los valores de enumeración y la función ... lo que significa que si cambia la enumeración, debe cambiar la función para que coincida. Supongo que esto es cierto incluso para un std :: map.
Recuerdo vagamente que encontramos una utilidad para generar el código de función a partir del código de enumeración. La longitud de la tabla de enumeración había aumentado a varios cientos ... y en algún momento tal vez sea una buena opción escribir código para escribir código.
Nota -
en un esfuerzo de mejora del sistema integrado, mi equipo reemplazó muchas tablas (100+?) de cadenas terminadas en nulo que se usaron para asignar los valores enum int a sus cadenas de texto.
El problema con las tablas fue que a menudo no se notaba un valor fuera del rango porque muchas de estas tablas se reunieron en una región de código / memoria, de manera que un valor fuera del rango alcanzó el final de la tabla nombrada y devolvió una cadena terminada en nulo de alguna tabla posterior.
El uso de la sentencia function-with-switch también nos permitió agregar una aserción en la cláusula predeterminada del switch. Las afirmaciones encontraron varios errores de codificación más durante la prueba, y nuestras afirmaciones se vincularon a un registro de sistema de RAM estático que nuestros técnicos de campo podían buscar.
Aquí hay otro buen truco para definir la enumeración usando X Macro:
#include <iostream>
#define WEEK_DAYS /
X(MON, "Monday", true) /
X(TUE, "Tuesday", true) /
X(WED, "Wednesday", true) /
X(THU, "Thursday", true) /
X(FRI, "Friday", true) /
X(SAT, "Saturday", false) /
X(SUN, "Sunday", false)
#define X(day, name, workday) day,
enum WeekDay : size_t
{
WEEK_DAYS
};
#undef X
#define X(day, name, workday) name,
char const *weekday_name[] =
{
WEEK_DAYS
};
#undef X
#define X(day, name, workday) workday,
bool weekday_workday[]
{
WEEK_DAYS
};
#undef X
int main()
{
std::cout << "Enum value: " << WeekDay::THU << std::endl;
std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;
WeekDay wd = SUN;
std::cout << "Enum value: " << wd << std::endl;
std::cout << "Name string: " << weekday_name[wd] << std::endl;
std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;
return 0;
}
Demostración en vivo: https://ideone.com/bPAVTM
Salidas:
Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false
He tenido un éxito excelente con una técnica que se parece a las macros X apuntadas por @RolandXu. También hicimos un uso intensivo del operador de cuerdas. La técnica mitiga la pesadilla de mantenimiento cuando tienes un dominio de aplicación donde los elementos aparecen como cadenas y como fichas numéricas.
Es particularmente útil cuando la documentación legible por máquina está disponible para que las líneas de la macro X (...) puedan generarse automáticamente. Una nueva documentación daría como resultado inmediatamente una actualización consistente del programa que cubriera las cadenas, enumeraciones y los diccionarios que se traducen entre ellos en ambas direcciones. (Estábamos tratando con tokens PCL6).
Y mientras que el código del preprocesador parece bastante feo, todos esos aspectos técnicos se pueden ocultar en los archivos de encabezado que nunca deben tocarse nuevamente, y tampoco lo hacen los archivos de origen. Todo es de tipo seguro. Lo único que cambia es un archivo de texto que contiene todas las líneas X (...), y posiblemente se genere automáticamente.
No se puede directamente, enum
en C ++ no son como enums de Java.
El enfoque habitual es crear un std::map<WeekEnum,std::string>
.
std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
Puede definir un operador que realice la salida.
std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
switch(e) {
case Monday: lhs << "Monday"; break;
.. etc
}
return lhs;
}
Si conoce las etiquetas de enumeración reales correlacionadas con sus valores, puede usar contenedores y std::string_view
C ++ 17 para acceder rápidamente a los valores y sus representaciones de cadena con el operador [
]
mientras lo rastrea. std::string_view
solo asignará memoria cuando se cree. También pueden designarse con static constexpr
si desea que estén disponibles en tiempo de ejecución para obtener más ahorros de rendimiento. Esta pequeña aplicación de consola debería ser bastante rápida.
#include <iostream>
#include <string_view>
#include <tuple>
int main() {
enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
static constexpr std::string_view Monday = "Monday";
static constexpr std::string_view Tuesday = "Tuesday";
static constexpr std::string_view Wednesday = "Wednesday";
static constexpr std::string_view Thursday = "Thursday";
static constexpr std::string_view Friday = "Friday";
static constexpr std::string_view Saturday = "Saturday";
static constexpr std::string_view Sunday = "Sunday";
static constexpr std::string_view opener = "enum[";
static constexpr std::string_view closer = "] is ";
static constexpr std::string_view semi = ":";
std::pair<Weekdays, std::string_view> Weekdays_List[] = {
std::make_pair(Weekdays::Monday, Monday),
std::make_pair(Weekdays::Tuesday, Tuesday),
std::make_pair(Weekdays::Wednesday, Wednesday),
std::make_pair(Weekdays::Thursday, Thursday),
std::make_pair(Weekdays::Friday, Friday),
std::make_pair(Weekdays::Saturday, Saturday),
std::make_pair(Weekdays::Sunday, Sunday)
};
for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi/
<<(int)Weekdays_List[(int)i].first<<std::endl;
}
return 0;
}
Salida:
enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6
Una enumeración es algo así como una matriz inversa. Lo que creo que quieres es esto:
const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!"; // Or whatever you''de like to do with it.
no, no tiene forma de obtener el "nombre" del valor en C ++ porque todos los símbolos se descartan en la compilación.
Es posible que necesites X Macros