Jest inne rozwiązanie: utwórz własną dynamiczną klasę wyliczania. Oznacza, że masz funkcję structi jakąś funkcję do tworzenia nowego wyliczenia, które przechowuje elementy w a, structa każdy element ma ciąg znaków dla nazwy. Potrzebujesz także typu do przechowywania poszczególnych elementów, funkcji do ich porównywania i tak dalej. Oto przykład:
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Enumeration_element_T
{
size_t index;
struct Enumeration_T *parrent;
char *name;
};
struct Enumeration_T
{
size_t len;
struct Enumeration_element_T elements[];
};
void enumeration_delete(struct Enumeration_T *self)
{
if(self)
{
while(self->len--)
{
free(self->elements[self->len].name);
}
free(self);
}
}
struct Enumeration_T *enumeration_create(size_t len,...)
{
struct Enumeration_T *self=malloc(sizeof(self)+sizeof(self->elements[0])*len);
if(!self)
{
return NULL;
}
self->len=0;
va_list l;
va_start(l,len);
for(size_t i=0;i<len;i++)
{
const char *name=va_arg(l,const char *);
self->elements[i].name=malloc(strlen(name)+1);
if(!self->elements[i].name)
{
enumeration_delete(self);
return NULL;
}
strcpy(self->elements[i].name,name);
self->len++;
}
return self;
}
bool enumeration_isEqual(struct Enumeration_element_T *a,struct Enumeration_element_T *b)
{
return a->parrent==b->parrent && a->index==b->index;
}
bool enumeration_isName(struct Enumeration_element_T *a, const char *name)
{
return !strcmp(a->name,name);
}
const char *enumeration_getName(struct Enumeration_element_T *a)
{
return a->name;
}
struct Enumeration_element_T *enumeration_getFromName(struct Enumeration_T *self, const char *name)
{
for(size_t i=0;i<self->len;i++)
{
if(enumeration_isName(&self->elements[i],name))
{
return &self->elements[i];
}
}
return NULL;
}
struct Enumeration_element_T *enumeration_get(struct Enumeration_T *self, size_t index)
{
return &self->elements[index];
}
size_t enumeration_getCount(struct Enumeration_T *self)
{
return self->len;
}
bool enumeration_isInRange(struct Enumeration_T *self, size_t index)
{
return index<self->len;
}
int main(void)
{
struct Enumeration_T *weekdays=enumeration_create(7,"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
if(!weekdays)
{
return 1;
}
printf("Please enter the day of the week (0 to 6)\n");
size_t j = 0;
if(scanf("%zu",&j)!=1)
{
enumeration_delete(weekdays);
return 1;
}
if(!enumeration_isInRange(weekdays,j))
{
enumeration_delete(weekdays);
return 1;
}
struct Enumeration_element_T *day=enumeration_get(weekdays,j);
printf("%s\n",enumeration_getName(day));
enumeration_delete(weekdays);
return 0;
}
Funkcje wyliczania powinny znajdować się we własnej jednostce tłumaczeniowej, ale połączyłem je tutaj, aby było to prostsze.
Zaletą jest to, że to rozwiązanie jest elastyczne, działa na zasadzie DRY, możesz przechowywać informacje wraz z każdym elementem, możesz tworzyć nowe wyliczenia w trakcie działania, a także dodawać nowe elementy w trakcie działania. Wadą jest to, że jest to złożone, wymaga dynamicznej alokacji pamięci, nie może być używane w switch- case, wymaga więcej pamięci i jest wolniejsze. Pytanie brzmi, czy nie powinieneś używać języka wyższego poziomu w przypadkach, gdy tego potrzebujesz.