|
Инкрементирующийся define, c помощью препроцессор Си |
|
|
|
Jul 10 2016, 06:40
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Здравствуйте. Написан конечный автомат на конструкции switch - case. Для перехода к последующему действию просто инкрементируется указатель: Код switch(i) { case 0: ... i++; case 1: ... i++; ... case N: ... i++; } Действий порядка 100 и возникла проблема с добавлением новых case-обработчиков в середину конструкции, т.к. приходится увеличивать все последующие номера case. Хочется перенести эту задачу на плечи препроцессора и оформить конструкцию таким образом, чтобы название макроопределения case было у всех одинаковым и, в тоже время, каждое последующее значение было на 1 больше предыдущего: Код switch(i) { case INCNAME: ... i++; case INCNAME: ... i++; ... case INCNAME: ... i++; } Подскажите, пожалуйста, возможно ли это как-то реализовать? Спасибо.
|
|
|
|
|
 |
Ответов
(1 - 14)
|
Jul 10 2016, 06:49
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Так получится? Код int j = 0;
if(0){} else if((j++) && (i == j)) { // do 1 i++; } else if((j++) && (i == j)) { // do 2 i++; } ... else if((j++) && (i == j)) { // do N i++; } Код #define NEXT else if((j++) && (i==j))
if(0){} NEXT { } NEXT { }
|
|
|
|
|
Jul 10 2016, 07:27
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
"В лоб" задача решается применением enum. CODE typedef enum { IDLE, START, RUN, STOP } state_t;
state_t State;
switch (State) { case IDLE: ..... State = START; break;
case START: .... В середину такого конечного автомата легко добавляется любое количество новых состояний. Конечно, придумать около 100 названий для сотояний и не сорваться на использование цифр в этих названиях - задача непростая.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 10 2016, 07:30
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Alt.F4 @ Jul 10 2016, 12:40)  Действий порядка 100 и возникла проблема с добавлением новых case-обработчиков в середину конструкции, т.к. приходится увеличивать все последующие номера case. Хочется перенести эту задачу на плечи препроцессора и оформить конструкцию таким образом, чтобы название макроопределения case было у всех одинаковым и, в тоже время, каждое последующее значение было на 1 больше предыдущего: Значения после case должны быть разными. Иначе компилятор просто не станет компилить. Я в подобных случаях использую enum. При добавлении хоть в середину хоть в конец нет проблем с перенумерацией. enum { //фазы автомата состояний INCNAME_SOST0, INCNAME_SOST1, INCNAME_SOST2, ...}; Цитата(adnega @ Jul 10 2016, 12:49)  Так получится? else if((j++) && (i == j)) ... Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".
|
|
|
|
|
Jul 10 2016, 07:47
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(jcxz @ Jul 10 2016, 10:30)  Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior". Компилируется даже без предупреждений. Единственное, в {} не должно быть i++. Лучше new_i++, а в самом конце i = new_i. Иначе автомат выстрелит очередью.
|
|
|
|
|
Jul 10 2016, 08:19
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Alt.F4 @ Jul 10 2016, 09:40)  Подскажите, пожалуйста, возможно ли это как-то реализовать? Спасибо. Создаете в Excel одну строку с одним макроопределением. Потом протягиваете ее до 100 строк и получаете идеальный инкремент. Если нужно вставить что-то в середину, то в вставляете в Excel-е и снова протягиваете, получите новый инкремент. Потом Copy-Paste из Excel-а
А числа на макросы заменяются автоматически с использованием регулярного выражения.
|
|
|
|
|
Jul 10 2016, 08:38
|
Частый гость
 
Группа: Участник
Сообщений: 168
Регистрация: 14-02-10
Пользователь №: 55 490

|
Подход с enum, несомненно, правилен. Однако, при добавлении состояний, потребуется редактировать в двух местах. Код #define INCNAME __COUNTER__ Только надо предусмотреть ловушку какую на случай если __COUNTER__ был ранее использован. https://gcc.gnu.org/onlinedocs/cpp/Common-P...edefined-Macros
--------------------
#define TRUE (4==(2*2))
|
|
|
|
|
Jul 10 2016, 09:54
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(zltigo @ Jul 10 2016, 12:49)  Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик  . Думайте о комбинации методов. Да нормально, есть прикладные протоколы с очень большими словарями. Только вот enum для этого негодное средство, поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.
|
|
|
|
|
Jul 10 2016, 10:26
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(AlexandrY @ Jul 10 2016, 12:54)  Да нормально, есть прикладные протоколы с очень большими словарями. Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус. Цитата(AlexandrY @ Jul 10 2016, 12:54)  Только вот enum для этого негодное средство, поскольку при отладке... Отладка сколь-нибудь серьезных ПРОТОКОЛОВ отладчиком есть абсолютно непригодное средство, ибо все проблемы взаимодействия оборудования раснообразных производителей начнутся не тогда, когда все лежит на столе. Так что логирование состояния конечного автомата обязательно, ну а при логировании разворачивание названий состояний в текст так же обязательно. Все это решается через общую функцию изменения состояния автомата. Например: Код void q921_set_state( LAPD_t *ldp, ulong new_state ) { ldp->state = new_state; dprintf( "\tL%1X:Set State`%s`(Cmd:%4X)\r", ldp->ch, q2_states[ldp->state], ldp->q921_cmd ); }
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jul 10 2016, 11:49
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(zltigo @ Jul 10 2016, 13:26)  Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус. Отладка сколь-нибудь серьезных ПРОТОКОЛОВ отладчиком есть абсолютно непригодное средство, ибо все проблемы взаимодействия оборудования раснообразных производителей начнутся не тогда, когда все лежит на столе. Прямо сейчас у меня в работе протокол с 41-им case в парсере. Линейная структура кода позволяет легко его форматировать и рефакторить. Регулярные выражения замены легче писать под такую структуру кода. Работает она быстрее. Короче одни плюсы. Протоколы только отладчиком через SWD и можно детально отладить. Логи для протоколов - это во первых медленно, во вторых менее информативно, в третьих сами вносят нежелательный эффект в виде роста стека задач и ухудшения реалтайма.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|