Технический приём для формирования согласованных данных - C (СИ)
Формулировка задачи:
Кому-то может пригодиться
Если нет чёткого представления о том, как работает препроцессирование, то смотрим сюда (про директиву #include) и сюда (про директиву #define)
Допустим, нужно сделать две согласованных конструкции
При этом элемент enum'а является индексом в массив, для доставания соотвествующего строкового значения. Если нам нужно что-то добавить, то надо править в двух местах, которые, как правило в разных файлах. А когда файлы большие и подобных данных много, то можно запутаться. Если изменить только enum (особенно если добавить элемент в середину), то names станет несогласованным.
А потому нужно такое решение, чтобы каждый элемент условно задавался одной строкой, чтобы во все места подставились нужные данные. Для этого делаю дополнительный файл. У меня он имеет расширение *.def, но это непринципииально (у gnu'шников он *.def, а потому я тоже так делаю, чтобы как у людей было)
В итоге получается такая штука
В итоге после подстановки директив #include на этапе прероцессирования получаем файл
Теперь смотрим, как макросы подстанавливаются
раскроется как
а
раскроется как
В итоге весь файл после препроцессирования окажется вот таким
Такми образом инициализаторы от двух разных конструкций у на оказываются в одной строке. Добавление новых элементов о\существляется только в файл *.def
enum { ENUM_VAL1, ENUM_VAL2, ENUM_VAL3, }; char *names[] = { "VAL1", "VAL2", "VAL3", };
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")
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", };
Решение задачи: «Технический приём для формирования согласованных данных»
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 };
Объяснение кода листинга программы
В представленном коде используется препроцессор для формирования согласованных данных. Список именованных чисел и их значений в виде перечисления (enum) и массива строк (char *names[]) формируются из данных, которые находятся в файлах file1.def и file2.def. Список элементов перечисления формируется следующим образом:
- enum — объявление перечисления.
- #define DEF_ELEM(p1,p2) p1, — определение элемента перечисления. Значение —
p1
, имя —p2
. - #include
file1.def
— включение содержимого файла file1.def. - #undef DEF_ELEM — отмена определения элемента перечисления.
- #define DEF_ELEM(p1,p2) p1 — определение элемента перечисления. Значение —
p1
, имя —p2
. - #include
file2.def
— включение содержимого файла file2.def. - #undef DEF_ELEM — отмена определения элемента перечисления.
Список строк формируется аналогично, только вместо значений используется строка, которая идет после определения элемента перечисления.
В результате, в переменной
names
будет храниться массив строк, а в переменнойenum
— перечисление, которые будут содержать согласованные данные из файлов file1.def и file2.def.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д