Перейти к содержанию
    

Инкрементирующийся define

Здравствуйте.

 

Написан конечный автомат на конструкции 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++;
}

Подскажите, пожалуйста, возможно ли это как-то реализовать?

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так получится?

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
{
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"В лоб" задача решается применением enum.

typedef enum
{
      IDLE,
      START,
      RUN,
      STOP
} state_t;

state_t State;


switch (State)
{
case IDLE:
    .....
    State = START;
    break;

case START:
    ....

В середину такого конечного автомата легко добавляется любое количество новых состояний. Конечно, придумать около 100 названий для сотояний и не сорваться на использование цифр в этих названиях - задача непростая.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Действий порядка 100 и возникла проблема с добавлением новых case-обработчиков в середину конструкции, т.к. приходится увеличивать все последующие номера case.

Хочется перенести эту задачу на плечи препроцессора и оформить конструкцию таким образом, чтобы название макроопределения case было у всех одинаковым и, в тоже время, каждое последующее значение было на 1 больше предыдущего:

Значения после case должны быть разными. Иначе компилятор просто не станет компилить.

Я в подобных случаях использую enum. При добавлении хоть в середину хоть в конец нет проблем с перенумерацией.

enum { //фазы автомата состояний

INCNAME_SOST0, INCNAME_SOST1, INCNAME_SOST2, ...};

 

Так получится?

else if((j++) && (i == j))

...

Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".

Компилируется даже без предупреждений.

Единственное, в {} не должно быть i++.

Лучше new_i++, а в самом конце i = new_i.

Иначе автомат выстрелит очередью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите, пожалуйста, возможно ли это как-то реализовать?

Спасибо.

Создаете в Excel одну строку с одним макроопределением.

Потом протягиваете ее до 100 строк и получаете идеальный инкремент.

Если нужно вставить что-то в середину, то в вставляете в Excel-е и снова протягиваете, получите новый инкремент.

Потом Copy-Paste из Excel-а

post-2050-1468138160_thumb.png

 

А числа на макросы заменяются автоматически с использованием регулярного выражения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подход с enum, несомненно, правилен.

Однако, при добавлении состояний, потребуется редактировать в двух местах.

#define INCNAME __COUNTER__

Только надо предусмотреть ловушку какую на случай если __COUNTER__ был ранее использован.

https://gcc.gnu.org/onlinedocs/cpp/Common-P...edefined-Macros

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть такая реализация, сделана на swich/case и __LINE__

http://dunkels.com/adam/pt/index.html

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Действий порядка 100...

Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик :(.

Думайте о комбинации методов. Более-менее типичный выход из такой ситуации это использование наряду с состоянием конечного автомата дополнительных битовых флагов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик :(.

Думайте о комбинации методов.

Да нормально, есть прикладные протоколы с очень большими словарями.

 

Только вот enum для этого негодное средство,

поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да нормально, есть прикладные протоколы с очень большими словарями.

Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус.

Только вот 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 );
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус.

Отладка сколь-нибудь серьезных ПРОТОКОЛОВ отладчиком есть абсолютно непригодное средство, ибо все проблемы взаимодействия оборудования раснообразных производителей начнутся не тогда, когда все лежит на столе.

Прямо сейчас у меня в работе протокол с 41-им case в парсере.

 

Линейная структура кода позволяет легко его форматировать и рефакторить.

Регулярные выражения замены легче писать под такую структуру кода.

Работает она быстрее.

Короче одни плюсы. :biggrin:

 

Протоколы только отладчиком через SWD и можно детально отладить.

Логи для протоколов - это во первых медленно, во вторых менее информативно, в третьих сами вносят нежелательный эффект в виде роста стека задач и ухудшения реалтайма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только вот enum для этого негодное средство,

поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.

Вот этого не понял. Мой отладчик пишет численное значение при помещени указателя мыши на имя. Да и небходимость узнать конкретное значение возникает очень редко, чаще гораздо важнее знать именно имя состояния конечного автомата.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мой отладчик пишет численное значение при помещени указателя мыши на имя.

 

Трудно припомнить название? :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...