Технический приём для формирования согласованных данных - C (СИ)

Формулировка задачи:

Кому-то может пригодиться Если нет чёткого представления о том, как работает препроцессирование, то смотрим сюда (про директиву #include) и сюда (про директиву #define) Допустим, нужно сделать две согласованных конструкции
enum
{
  ENUM_VAL1,
  ENUM_VAL2,
  ENUM_VAL3,
};
 
char *names[] =
{
  "VAL1",
  "VAL2",
  "VAL3",
};
При этом элемент enum'а является индексом в массив, для доставания соотвествующего строкового значения. Если нам нужно что-то добавить, то надо править в двух местах, которые, как правило в разных файлах. А когда файлы большие и подобных данных много, то можно запутаться. Если изменить только enum (особенно если добавить элемент в середину), то names станет несогласованным. А потому нужно такое решение, чтобы каждый элемент условно задавался одной строкой, чтобы во все места подставились нужные данные. Для этого делаю дополнительный файл. У меня он имеет расширение *.def, но это непринципииально (у gnu'шников он *.def, а потому я тоже так делаю, чтобы как у людей было) В итоге получается такая штука
enum
{
#define DEF_ELEM(p1,p2) p1,
#include "file.def"
#undef DEF_ELEM
};
 
char *names[] =
{
#define DEF_ELEM(p1,p2) p2,
#include "file.def"
#undef DEF_ELEM
};
/* Файл file.def */
DEF_ELEM (ENUM_VAL1, "VAL1")
DEF_ELEM (ENUM_VAL2, "VAL2")
DEF_ELEM (ENUM_VAL3, "VAL3")
В итоге после подстановки директив #include на этапе прероцессирования получаем файл
enum
{
#define DEF_ELEM(p1,p2) p1,
DEF_ELEM (ENUM_VAL1, "VAL1")
DEF_ELEM (ENUM_VAL2, "VAL2")
DEF_ELEM (ENUM_VAL3, "VAL3")
#undef DEF_ELEM
};
 
char *names[] =
{
#define DEF_ELEM(p1,p2) p2,
DEF_ELEM (ENUM_VAL1, "VAL1")
DEF_ELEM (ENUM_VAL2, "VAL2")
DEF_ELEM (ENUM_VAL3, "VAL3")
#undef DEF_ELEM
};
Теперь смотрим, как макросы подстанавливаются
#define DEF_ELEM(p1,p2) p1,
DEF_ELEM (ENUM_VAL1, "VAL1")
раскроется как
ENUM_VAL1,
а
#define DEF_ELEM(p1,p2) p2,
DEF_ELEM (ENUM_VAL1, "VAL1")
раскроется как
"VAL1",
В итоге весь файл после препроцессирования окажется вот таким
enum
{
ENUM_VAL1,
ENUM_VAL2,
ENUM_VAL3,
};
 
char *names[] =
{
"VAL1",
"VAL2",
"VAL3",
};
Такми образом инициализаторы от двух разных конструкций у на оказываются в одной строке. Добавление новых элементов о\существляется только в файл *.def

Код к задаче: «Технический приём для формирования согласованных данных - C (СИ)»

textual
enum
{
#define DEF_ELEM(p1,p2) p1,
#include "file1.def"
#undef DEF_ELEM
#define DEF_ELEM(p1,p2) p1
#include "file2.def"
#undef DEF_ELEM
};
 
char *names[] =
{
#define DEF_ELEM(p1,p2) p2,
#include "file1.def"
#undef DEF_ELEM
#define DEF_ELEM(p1,p2) p2
#include "file2.def"
#undef DEF_ELEM
};

14   голосов, оценка 4.000 из 5


СОХРАНИТЬ ССЫЛКУ