реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Инкрементирующийся define, c помощью препроцессор Си
Alt.F4
сообщение Jul 10 2016, 06:40
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 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++;
}

Подскажите, пожалуйста, возможно ли это как-то реализовать?
Спасибо.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 10 2016, 06:49
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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
{
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 07:27
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 07:30
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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".
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 10 2016, 07:47
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(jcxz @ Jul 10 2016, 10:30) *
Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".

Компилируется даже без предупреждений.
Единственное, в {} не должно быть i++.
Лучше new_i++, а в самом конце i = new_i.
Иначе автомат выстрелит очередью.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 08:19
Сообщение #6


Ally
******

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



Цитата(Alt.F4 @ Jul 10 2016, 09:40) *
Подскажите, пожалуйста, возможно ли это как-то реализовать?
Спасибо.

Создаете в Excel одну строку с одним макроопределением.
Потом протягиваете ее до 100 строк и получаете идеальный инкремент.
Если нужно вставить что-то в середину, то в вставляете в Excel-е и снова протягиваете, получите новый инкремент.
Потом Copy-Paste из Excel-а
Прикрепленное изображение


А числа на макросы заменяются автоматически с использованием регулярного выражения.
Go to the top of the page
 
+Quote Post
Владивольт
сообщение Jul 10 2016, 08:38
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 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))
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 10 2016, 09:03
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Есть такая реализация, сделана на swich/case и __LINE__
http://dunkels.com/adam/pt/index.html
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2016, 09:49
Сообщение #9


Гуру
******

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



QUOTE (Alt.F4 @ Jul 10 2016, 09:40) *
Действий порядка 100...

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 09:54
Сообщение #10


Ally
******

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



Цитата(zltigo @ Jul 10 2016, 12:49) *
Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик sad.gif.
Думайте о комбинации методов.

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

Только вот enum для этого негодное средство,
поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2016, 10:26
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 11:49
Сообщение #12


Ally
******

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



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

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

Линейная структура кода позволяет легко его форматировать и рефакторить.
Регулярные выражения замены легче писать под такую структуру кода.
Работает она быстрее.
Короче одни плюсы. biggrin.gif

Протоколы только отладчиком через SWD и можно детально отладить.
Логи для протоколов - это во первых медленно, во вторых менее информативно, в третьих сами вносят нежелательный эффект в виде роста стека задач и ухудшения реалтайма.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 11:55
Сообщение #13


Гуру
******

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



QUOTE (AlexandrY @ Jul 10 2016, 12:54) *
Только вот enum для этого негодное средство,
поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.
Вот этого не понял. Мой отладчик пишет численное значение при помещени указателя мыши на имя. Да и небходимость узнать конкретное значение возникает очень редко, чаще гораздо важнее знать именно имя состояния конечного автомата.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 12:02
Сообщение #14


Ally
******

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



Цитата(Сергей Борщ @ Jul 10 2016, 14:55) *
Мой отладчик пишет численное значение при помещени указателя мыши на имя.


Трудно припомнить название? biggrin.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 12:40
Сообщение #15


Гуру
******

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



QUOTE (AlexandrY @ Jul 10 2016, 15:02) *
Трудно припомнить название? biggrin.gif
gdb + eclipse.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 13:56
Сообщение #16


Ally
******

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



Цитата(Сергей Борщ @ Jul 10 2016, 15:40) *
gdb + eclipse.


Понятно. Я всегда говорил, что языки это эхо средств редактирования и отладки.
А вот в IAR и Keil применение enum будет неудобным.
Я, кстати, enum уже давно не применяю. Одни проблемы от них.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 19:12
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(zltigo @ Jul 10 2016, 15:49) *
Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик sad.gif.

Можно сделать завуалированный конечный автомат, без огромных перечислений enum. На стеке.
Будет что-то типа задачи со своим стеком, очередное состояние - это собственно адрес. Вход в автомат - это переключение на его стек, выход (там где был break) - обратное переключение на исходный стек.
Очень удобно отлаживать. Но конечно требуется некоторая дополнительная память (стек).
Я так иногда делаю когда автомат получается ну очень сложным, да ещё с вложенными ветками.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 20:00
Сообщение #18


Ally
******

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



Цитата(jcxz @ Jul 10 2016, 22:12) *
Я так иногда делаю когда автомат получается ну очень сложным, да ещё с вложенными ветками.


Где же тут удобство?
Вижу только проблемы для статического анализатора.
Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны.
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 10 2016, 20:33
Сообщение #19


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Зря не смотрели в сторону
http://dunkels.com/adam/pt/index.html
и enum не нужны
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 20:36
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AlexandrY @ Jul 11 2016, 02:00) *
Где же тут удобство?
Вижу только проблемы для статического анализатора.
Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны.

А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода.
Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную.
Удобство в том хотя-бы, что код линеен, а не вермишель из case ...
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 11 2016, 07:01
Сообщение #21


Ally
******

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



Цитата(jcxz @ Jul 10 2016, 23:36) *
А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода.
Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную.
Удобство в том хотя-бы, что код линеен, а не вермишель из case ...

Хоть я и не совсем понимаю о чем вы говорите, поскольку не видно кода, но могу уверенно сказать, что ваш код не линейный, а размазанный.
Т.е. часть логики кода отнесена куда-то в таблицы.
А это еще хуже вермишели для понимания работы.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 11 2016, 08:13
Сообщение #22


Гуру
******

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



QUOTE (AlexandrY @ Jul 10 2016, 14:49) *
Прямо сейчас у меня в работе протокол с 41-им case в парсере.

В Вашим? Да хоть 4141 case. Это ВАША РЕАЛИЗАЦИЯ некоего протокола, которая делатся через ... Попытайтесь найти спецификацию протокола в котором используется такое количество СОСТОЯНИЙ хоть на каком-то уровне.
QUOTE
Протоколы только отладчиком через SWD и можно детально отладить.

... поехав на край земли с "отладчиком" и сидя на столбе выяснять что это, вдруг, от того, что на противоположном конце земли кто-то, например, заапгрейдил Cisco не может связаться с Магаданом. Да, да внутрисхемный отладчик это очень "полезная" штука в таких ситуациях sm.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 11 2016, 08:14
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AlexandrY @ Jul 11 2016, 13:01) *
Хоть я и не совсем понимаю о чем вы говорите, поскольку не видно кода, но могу уверенно сказать, что ваш код не линейный, а размазанный.
Т.е. часть логики кода отнесена куда-то в таблицы.
А это еще хуже вермишели для понимания работы.

Примерно так (код вне к.автомата - там где у ТС switch; код автомата - набор case-участков состояний к.автомата):
1. Выполняется код вне к.автомата. На месте switch() ставим переключение контекста на отдельный стек (в стеке сохранён контекст задачи автомата со всеми сохранёнными регистрами и адресом возврата).
SwitchContext(адрес_структуры_контекста_со_стеком).
Внутри функции SwitchContext() сохраняем текущий контекст на текущем стеке, переключаемся на стек к.автомата, восстанавливаем контекст из него и осуществляем возврат в код к.автомата.
В коде к.автомата, выполнив очередную ветку case, опять вызываем SwitchContext(), которая сохранит контекст к.автомата на его стеке, переключится на исходный стек задачи, вызвавшей к.автомат и восстановит контекст из него и осуществит возврат.
Код к. автомата будет выглядеть:
Код
код  //STATE_0
...    //STATE_0
SwitchContext(); //к.автомат перешёл в сост.1 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код  //STATE_1
...    //STATE_1
SwitchContext(); //к.автомат перешёл в сост.2 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_2
...      //STATE_2
if () { //STATE_2
  SwitchContext(); //к.автомат перешёл в сост.3 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_3
  ...      //STATE_3
} else {
  SwitchContext(); //к.автомат перешёл в сост.4 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_4
  ...      //STATE_4
}
SwitchContext(); //к.автомат перешёл в сост.5 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_5
...      //STATE_5
...

Как видите - код к.автомата получается линейным и легко читаемым даже при наличии ветвлений. А в традиционной реализации к.автомата при неск. ветвлениях по состояниям автомата уже получится малочитаемый вермишельный код.
А представьте, если вдруг окажется необходимым из некоторых состояний к.автомата проходить цепочку других его состояний с возвратом потом в исходную точку:
сост0
сост1
сост10
сост11
сост12
сост2
...
сост5
сост6
сост10
сост11
сост12
сост7
...
В традиционной реализации придётся ещё куда-то сохранять/восстаналивать состояния автомата. И вообще получится лес.
А с переключением контекста, будет просто вызов функции.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 11 2016, 08:22
Сообщение #24


Гуру
******

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



QUOTE (jcxz @ Jul 10 2016, 22:12) *
Можно сделать завуалированный конечный автомат, без огромных перечислений enum....

Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки sm.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 11 2016, 08:34
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(zltigo @ Jul 11 2016, 14:22) *
Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки sm.gif

Это да, можно и так.
Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата.
Я не говорю конкретно про разбор кадров протокола, вопрос был общего плана об к.автоматах.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 11 2016, 08:48
Сообщение #26


Ally
******

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



Цитата(x893 @ Jul 10 2016, 23:33) *
Зря не смотрели в сторону
http://dunkels.com/adam/pt/index.html
и enum не нужны

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

Цитата(jcxz @ Jul 11 2016, 11:14) *
Код
код  //STATE_0
...    //STATE_0
SwitchContext(); //к.автомат перешёл в сост.1 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код  //STATE_1
...    //STATE_1
SwitchContext(); //к.автомат перешёл в сост.2 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_2
...      //STATE_2
if () { //STATE_2
  SwitchContext(); //к.автомат перешёл в сост.3 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_3
  ...      //STATE_3
} else {
  SwitchContext(); //к.автомат перешёл в сост.4 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_4
  ...      //STATE_4
}
SwitchContext(); //к.автомат перешёл в сост.5 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_5
...      //STATE_5
...

В вашем псевдокоде я вижу только множественные SwitchContext() без аргументов. Это выглядит как полная бессмыслица.
Стек - это в вашем понятии стековая структура данных или стек процессора?
Стековые структуры обычно применяют для раскрытия рекурсии в парсерах. У меня так работают парсеры JSON, LUA и еще несколько.

Но в протоколах нет рекурсий. Там есть именно разбор вариантных хидеров. Ничего лучше case для этого не придумано.
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 11 2016, 09:09
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Protothread это скрытый switch без enum и прочей ерунды.
Контекст всегда можно сделать структурой и устанавливать указатель при входе.
Ограничение только на динамические переменные.
Смысл простой - использование __LINE__ для автогенерации switch/case
Всё остальное - как угодно.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 11 2016, 09:24
Сообщение #28


Ally
******

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



Цитата(x893 @ Jul 11 2016, 12:09) *
Смысл простой - использование __LINE__ для автогенерации switch/case

Да понятен там смысл.
Но влетать внутрь цикла, дескать C-и позволяет это хуже чем goto.
Опять же при символьной отладке это будет выглядеть как хаотичная передача управления непонятно куда.

TC же показал способ с вычисляемыми ключами. Ему Protothread никак не подойдет.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 11 2016, 09:55
Сообщение #29


Гуру
******

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



Цитата(jcxz @ Jul 11 2016, 11:34) *
Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата.

Несомненно! По этой причине я тоже с самого начала писал, что просто не надо все всегда ТОЛЬКО на состояния автомата валить. В каждом конкретом случае надо смотреть, как разгружать собственно автомат от излишества состояний, ибо конечный автомат не есть панацея sad.gif. Совсем недавно в казалось-бы простой задаче начал в лоб писать автомат - началось погружение в пучину состояний. Разбил на два автомата - тоже не сильно понравилось, ибо такой подход нормально работает, когда протокол на уровни бьется. В результате был сделан один автомат на 13 состояний и три бита дополнительных глобальных статусов.
Цитата(AlexandrY @ Jul 11 2016, 11:48) *
Но в протоколах нет рекурсий...

Это просто Ваши познания в протоколах невелики sad.gif. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 11 2016, 11:11
Сообщение #30


Ally
******

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



Цитата(zltigo @ Jul 11 2016, 12:55) *
Это просто Ваши познания в протоколах невелики sad.gif. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей.

Вы уж определитесь о чем хотите рассказать.
Сначала у вас многоуровневые концепции, теперь опять рекурсивные.

Фреймы из кусочков это связные списки, а не стековые структуры.
Я не видел рекурсию на в TCP/IP, ни в Zigbee, ни в BLE, ни в USB... Ну ни где.
А вы где усмотрели?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 11 2016, 11:43
Сообщение #31


Гуру
******

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



QUOTE (AlexandrY @ Jul 11 2016, 14:11) *
Вы уж определитесь о чем хотите рассказать.
Сначала у вас многоуровневые концепции, теперь опять рекурсивные.

О том, что и написал в первом посте. Если количество состояний автомата начинает измеряться десятками и тем более сотнями, то конечный автомат пишется НЕПРАВИЛЬНО. Как с этим бороться - рецепты разные. В том числе и рекурсия в явном или неявном виде.
QUOTE
Я не видел рекурсию на в TCP/IP, ни в Zigbee, ни в BLE, ни в USB... Ну ни где.

Вот я и говорю, что познания Ваши невелеки sad.gif.
Есть целые пласты протоколов находящиеся далеко за пределами сознания бытовых компьютерщиков. Они, напрмер, живут здесь: https://en.wikipedia.org/wiki/ITU-T отличительная их особенность, что создавались и оттачивались они годами и десятилениями и служат не для того, что бы какая нибудь фирма могла быстро родить урода по собственному невеликому разумению и засрать рынок заставля конкурентов ковыряться в дерьме добиваясь совместмости и работоспособности. А совсем с противоположной целью. При этом типовой ITU-ный стиль описания протоколов это конечные автоматы. Так уж получилось, что большую часть своей жизни я занимался именно телекомуникационными протоколами. Отчего и образовался более, чем скептический взгляд на то, что рожают и изобилии околокомпьютерщики и что является, как например, TCP/IP в лучшем случае огрызком давно существующих стеков протоколов.




--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Jul 11 2016, 12:10
Сообщение #32


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Не могли бы Вы, zltigo, уточнить в каком именно протоколе ITU-T рекурсивный разбор полей?
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 11 2016, 13:07
Сообщение #33


Ally
******

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



Цитата(Kabdim @ Jul 11 2016, 15:10) *
Не могли бы Вы, zltigo, уточнить в каком именно протоколе ITU-T рекурсивный разбор полей?


Он наверно имеет в виду DHCP где минимум 71 case в реализации.
Протоколы ITU-T из-за их всеядности и резиновости просто кошмарное количество switch-case требуют.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 11 2016, 13:24
Сообщение #34


Гуру
******

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



Цитата(Kabdim @ Jul 11 2016, 15:10) *
Не могли бы Вы, zltigo, уточнить в каком именно протоколе ITU-T рекурсивный разбор полей?

Как ТРЕБОВАНИЕ реализовывать что либо рекурсивно - естественно, в описании протоколов этого нет. Описание протроколов никак не описывает способов их реализации, хотя на верхнем уровне протокол описывается как конечный автомат и соответственно подталкивает на этот путь.
В конкретной реализации протокола все уже на откуп того, кто реализовывет. Я использовал рекурсивные вызовы автомата уже на уровне MTP3.
Цитата(AlexandrY @ Jul 11 2016, 16:07) *
Он наверно имеет в виду DHCP где минимум 71 case в реализации.

С каких пор студенческий самодуй DHСP стал иметь отношение к ITU? Разномастные огрызки разных RFC это вообще не стандарт.
Цитата
Протоколы ITU-T из-за их всеядности и резиновости просто кошмарное количество switch-case требуют.

ITU-T протоколы не требуют "кошмарных" количеств "case". По причине того, что они изначально разделены и хорошо суктурированы по уровням. Если же практическую реализацию делать бездумно смешивая в одну кучу что попало, то тогда, конечно, количество состояний для обеспечия функционирования можно раздувать хоть до "71" хоть до тысяч.
DHCP с 71 case, это как раз пример безмозглого подхода к делу sad.gif в стиле давай-давай, что тут думать трясти надо. Это обычно для "компьютерщиков", которые недоучившись и недопоняв сначала сотворив огрызок TCP/IP из того, что смогли понять в X.25 стеке, начали городить бездумно городить "протоколы" и дальше.
В результате начальное "упрощение", выкидывание, объедиение и усечение уровней ведет при попытке реализовать что либо сложнее, чем "два байта переслать" к каше из уровней, множества заплаток и появлениям "DHCP где минимум 71 case". Я все понимаю, почему так все растет - бурно в 70x началась компьютеоизация и микроконтролизация. Все сделать сразу по уму и аккуратно было сложно, или воообще почти невозможно из-за отсутсвия те-же аппаратных ресурсов. Мозговых ресурсов тоже не хватало - хлынул поток студентов нахватавшихся только вершков. Все понятно. И то, что выросло, то выросло http://inet777.ru/esli-byi-stroiteli-stroi...vilizaciyu/8476


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
k155la3
сообщение Jul 11 2016, 13:40
Сообщение #35


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Задавал я аналогичный вопрос
тут
но реализация через boost меня ужаснула.
Вместо С-препроцессора проще сделать свой для pre-build.
Так и сделал. Так и доволен сделаным.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jul 12 2016, 07:06
Сообщение #36


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



А я таки не понял, чем enum плох?
Мало того, что все по порядку, так можно добавить последний элемент eNumOfItems и получить автоматически количество элементов, которое можно вставить в определения массивов или в циклы, etc.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 12 2016, 08:26
Сообщение #37


Ally
******

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



Цитата(MrYuran @ Jul 12 2016, 10:06) *
А я таки не понял, чем enum плох?
Мало того, что все по порядку, так можно добавить последний элемент eNumOfItems и получить автоматически количество элементов, которое можно вставить в определения массивов или в циклы, etc.

Правильное тактическое применение enum это когда назначаешь переменной символьное имя и проверяешь всегда у нее только символьное имя.
А если надо enum сравнивать с int то это уже неправильное применение enum.
О чем отладчики и намекают не показывая числовое значение переменной с типом enum.
Цитата(zltigo @ Jul 11 2016, 16:24) *
Все сделать сразу по уму и аккуратно было сложно, или воообще почти невозможно из-за отсутсвия те-же аппаратных ресурсов. Мозговых ресурсов тоже не хватало - хлынул поток студентов нахватавшихся только вершков. Все понятно.

Это заблуждение разработчика видимо давно не имевшего практику разработки современных приложений.

Нынче длинные switch-case редко встретишь потому что протоколы разрослись настолько, что им этот механизм стал мал. Строят целы базы данных в виде таблиц с сотнями и тысячами записей.
Для такого switch-case просто физически писать уже невмоготу, потому при разборе протоколов переходят на движки с поиском по базе данных. Взгляните на ATT в BLE
Это ухудшает конечно производительность, но и процессоры стали быстрее.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 12 2016, 09:47
Сообщение #38


Гуру
******

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



QUOTE (AlexandrY @ Jul 12 2016, 11:26) *
Это заблуждение разработчика видимо давно не имевшего практику разработки современных приложений.

Это ЗНАНИЕ разработчика, который ЗНАЕТ, что если разрабатывать и писать реализации через анус, то case разрастаются немеряно. Что свидетельвует о НЕПРАВИЛЬНОМ подходе к реализации. О чем сразу в первом посте и написал. О том, что "современные" приложения рожают через анус, потому, что и ума и времени нехватает, тоже писал.
QUOTE
...писать уже невмоготу, потому при разборе протоколов переходят на движки с поиском по базе данных.

Теперь, если вернуться к TC и case, то очень, очень полагаю, что ничего сколь-нибудь выдающищегося и затмевающего своей сложностью "ATT в BLE" и иже с ним он не пишет, а просто и банально из-за необдуманости реализации тонет в плодящихся состояних конечного автомата sad.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 12 2016, 14:57
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Вообще то сам по себе инкремент состояния - это потенциальная угроза ошибки. Сейчас ручками вписываю конкретное текстовое состояние перехода (из enum, или enum+X-macro).


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Jul 13 2016, 05:15
Сообщение #40


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Я бы так делать не стал, но все же...

CODE
switch (i)
{
#define INC_DEF 0
#define TMP_DEF INC_DEF+1
case INC_DEF:
...
break;

#undef INC_DEF
#define INC_DEF TMP_DEF
#undef TMP_DEF
#define TMP_DEF INC_DEF+1

case INC_DEF:
...
break;

#undef INC_DEF
#define INC_DEF TMP_DEF
#undef TMP_DEF
#define TMP_DEF INC_DEF+1
case INC_DEF:
...
break;

#undef INC_DEF
#define INC_DEF TMP_DEF
#undef TMP_DEF
#define TMP_DEF INC_DEF+1

case INC_DEF:
...
break;

...
}

Go to the top of the page
 
+Quote Post
k155la3
сообщение Jul 13 2016, 06:36
Сообщение #41


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Если надо что-то "проинкриментировать" - надо сгенерировать некую таблицу (массив const структур во флеш), или несколько таблиц с требуемой инф-ей.
Опятьже - сделать свой препроцессор. ОНО будет читабельнее, логичнее без идиотизма когда средство важнее цели.
Если конечно цель - не сделать "глухой" проект, в котором только писатель и разбирается.


Цитата(Dog Pawlowa @ Jul 12 2016, 17:57) *
Вообще то сам по себе инкремент состояния - это потенциальная угроза ошибки. Сейчас ручками вписываю конкретное текстовое состояние перехода (из enum, или enum+X-macro).


Вот я по Вашей наводке так и делаю. Гранд мерси sm.gif
enum - генерация последовательных индексов массива,
и ониже - для инициализации массива констант-структур.
(реализация сколько-угодно-уровневого меню).

Сообщение отредактировал k155la3 - Jul 13 2016, 06:55
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Jul 13 2016, 07:01
Сообщение #42


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



k155la3

Ну успел отписаться до того, как Вы все удалили. Да, вы правы, это даже не скомпилится. Макроопределение - не переменная, она развертываются каждый раз заново, потому ошибка вылезет уже на втором переопределении. Виноват sad.gif
Go to the top of the page
 
+Quote Post
Andrew_Q
сообщение Jul 14 2016, 05:55
Сообщение #43





Группа: Участник
Сообщений: 7
Регистрация: 27-05-05
Пользователь №: 5 449



Я использую таблицу состояний автомата именно в виде таблицы во флеш, а парсер этой таблицы ее просто сканирует и выполняет действия в соответствии "состояние-событие-выполнить действие-перейти в новое состояние". В этом случае вся логика автомата содержится в таблице и любое добавление, удаление или редактирование любой строки влияет только на действия именно этой строки.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 14 2016, 07:53
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Andrew_Q @ Jul 14 2016, 08:55) *
Я использую таблицу состояний автомата именно в виде таблицы во флеш, а парсер этой таблицы ее просто сканирует и выполняет действия в соответствии "состояние-событие-выполнить действие-перейти в новое состояние". В этом случае вся логика автомата содержится в таблице и любое добавление, удаление или редактирование любой строки влияет только на действия именно этой строки.

А кто придумывает номера для "состояний"?
При добавлении новой записи нужно править поле "перейти в новое состояние" предыдущей записи?
Или можно ставить только поля "событие" и "выполнить действие" а выполняться все будет линейно пока не дойдет до конца таблицы?
Go to the top of the page
 
+Quote Post
Andrew_Q
сообщение Jul 14 2016, 09:04
Сообщение #45





Группа: Участник
Сообщений: 7
Регистрация: 27-05-05
Пользователь №: 5 449



Цитата(adnega @ Jul 14 2016, 12:53) *
А кто придумывает номера для "состояний"?
При добавлении новой записи нужно править поле "перейти в новое состояние" предыдущей записи?
Или можно ставить только поля "событие" и "выполнить действие" а выполняться все будет линейно пока не дойдет до конца таблицы?


Еще один enum

Если при правке выясняется, что нужно перейти в другое состояние, то да, нужно исправлять.
Если планируется, что все будет выполняться линейно, то это проще прописать в парсере один раз, тогда поле "перейти в состояние" в таблице отмирает.
Go to the top of the page
 
+Quote Post
Владивольт
сообщение Jul 14 2016, 09:14
Сообщение #46


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 14-02-10
Пользователь №: 55 490



Цитата(Andrew_Q @ Jul 14 2016, 09:55) *
состояние-событие-выполнить действие-перейти в новое состояние

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


--------------------
#define TRUE (4==(2*2))
Go to the top of the page
 
+Quote Post
k155la3
сообщение Jul 14 2016, 09:23
Сообщение #47


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(adnega @ Jul 14 2016, 10:53) *
А кто придумывает номера для "состояний"?
При добавлении новой записи нужно править поле "перейти в новое состояние" предыдущей записи?
Или можно ставить только поля "событие" и "выполнить действие" а выполняться все будет линейно пока не дойдет до конца таблицы?


Чтобы не заморачиваться с ручной адресацией массива-таблицы, можно примерно так.
(но таблиц нужно 2 - одна состояний, вторая - переходов, в которую включены указатели на функции-обработчики)
IMHO
Код
enum FSM_StateGo
{
    A1,
    A2,
    A3,
    A_Stop,
    B1,
    B2,
    B3,
    B_Stop,
    . . . .
};

enum FSM_State
{
    STATE_A,
    STATE_B
    . . .
};

TRun_Table RT[] =
{
[A1] = { STATE_A, A2 . . . . .  },
[A2] = { STATE_A, B2 . . . . .     },
[A3] = { STATE_A, A1 . . . . .  },
[A_STOP] = { STATE_A, A_STOP . . . . .  },
[B1] = { STATE_B, A2 . . . . .  },
[B2] = { STATE_B, B2 . . . . .     },
[B3] = { STATE_B, A1 . . . . .  },
[B_STOP] = { STATE_A, A_STOP . . . . .  },
. . . . .
};


Сообщение отредактировал k155la3 - Jul 14 2016, 09:36
Go to the top of the page
 
+Quote Post
Andrew_Q
сообщение Jul 14 2016, 09:29
Сообщение #48





Группа: Участник
Сообщений: 7
Регистрация: 27-05-05
Пользователь №: 5 449



Цитата(Владивольт @ Jul 14 2016, 14:14) *
Как быть с ветвлением, т.е. если новое состояние определяется исходом действия?


По исходу действия генерируем событие, в таблице описываем переход по этому событию в нужное состояние.

У меня таблица выглядит так

CODE
__flash state_table_type STATE_MODBUS_NASTER_TABLE[]= // Таблица состояний, условий перехода и действий режима ModBus мастер
{
/* из состояния по событию выполнить в состояние в режим */

{ANY_STATE, NOT_NET_ACCESS, init_state_mashine, INIT, MODBUS_MASTER},
{ANY_STATE, TIMER_OVFL, init_state_mashine, INIT, MODBUS_MASTER},
{INIT, NET_ACCESS, request_ana_from_monoblock, WAIT_MONOBLOCK_ANA, MODBUS_MASTER},
{WAIT_MONOBLOCK_ANA, MONOBLOCK_DATA_RECEIVED,send_ana_to_modbus, WAIT_CHECK_MODBUS_ANA, MODBUS_MASTER},
{WAIT_CHECK_MODBUS_ANA, MODBUS_SENDED, receive_ana_modbus_check, NO_NEW_STATE, MODBUS_MASTER},
{WAIT_CHECK_MODBUS_ANA, MODBUS_RECEIVED, test_ana_modbus_check, NO_NEW_STATE, MODBUS_MASTER},
}
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 14 2016, 09:45
Сообщение #49


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Andrew_Q @ Jul 14 2016, 12:29) *
__flash state_table_type STATE_MODBUS_NASTER_TABLE[]=

Терминология MONOBLOCK и _ana_ не из оперы modbus. Всегда поражаюсь людям изобретающим велосипеды...

Цитата
PDU (Protocol Data Unit) — общая для всех физических уровней часть пакета MODBUS. Включает в себя код функции и данные пакета.
ADU (Application Data Unit) — полный пакет MODBUS. Включает в себя специфичную для физического уровня часть пакета и PDU.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Andrew_Q
сообщение Jul 14 2016, 09:50
Сообщение #50





Группа: Участник
Сообщений: 7
Регистрация: 27-05-05
Пользователь №: 5 449



Опечатка?
Я хронический лентяй, программа работает на изделии с 2002 года. Исправлять лениво :-)

Цитата(demiurg_spb @ Jul 14 2016, 14:45) *
Терминология MONOBLOCK не из оперы modbus. Всегда поражаюсь людям изобретающим велосипеды...


Моноблок - это блоки нашей разработки на кастомном протоколе. А сие поделие является шлюзом в Modbus.

Вот, кстати, ссылка на автомат конечных состояний, описанный таблицей, управляемый событиями.
http://chipenable.ru/index.php/programming...nizatsiya-progr

Сообщение отредактировал Andrew_Q - Jul 14 2016, 10:05
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 15 2016, 03:26
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Andrew_Q @ Jul 14 2016, 15:29) *
По исходу действия генерируем событие, в таблице описываем переход по этому событию в нужное состояние.

А как быть если после некоторых состояний необходимо пройти через определённую цепочку состояний, а затем вернуться к исходной цепочке? И так - в разных местах. rolleyes.gif
состояние1
состояние2
состояние10
состояние11
состояние12
состояние3
состояние4
состояние5
состояние10
состояние11
состояние12
состояние6
...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 15 2016, 03:47
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(jcxz @ Jul 15 2016, 06:26) *
А как быть если после некоторых состояний необходимо пройти через определённую цепочку состояний, а затем вернуться к исходной цепочке?

Ваш пример похож на последовательность выполнения строк на бэйсике, соответственно используется что-то типа GOSUB sm.gif
Ну и объединить цепочку состояний в одно состояние с дополнительным индексом ничего не мешает.
Регулярность и простота автоматов - хорошо, но все же иногда нужно немного и усложнять реализацию.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 15 2016, 05:11
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Dog Pawlowa @ Jul 15 2016, 09:47) *
Ваш пример похож на последовательность выполнения строк на бэйсике, соответственно используется что-то типа GOSUB sm.gif
Ну и объединить цепочку состояний в одно состояние с дополнительным индексом ничего не мешает.
Регулярность и простота автоматов - хорошо, но все же иногда нужно немного и усложнять реализацию.

Объединить? А что тогда мешает объединить все остальные состояния автомата в одно? Если ничего - то и автомат не нужен, так как всего одно состояние осталось. А если есть автомат - значит он для чего-то нужен и нельзя объединить состояния.
А если нужен доплнительный индекс, то как потом возвращаться к основному? А если не один уровень вложенности, а больше? Стек хранения состояний городить?
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 15 2016, 06:02
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(jcxz @ Jul 15 2016, 08:11) *
Объединить? А что тогда мешает объединить все остальные состояния автомата в одно? Если ничего - то и автомат не нужен, так как всего одно состояние осталось. А если есть автомат - значит он для чего-то нужен и нельзя объединить состояния.

Почему это нельзя объединить? Ну не будьте уж таким догматиком. Одну и ту же задачу могут выполнять автомат с одной переменной состояния, которое может принимать, допустим 16 значений и фрагмент программы, использующий 16 битовых флагов. И выглядеть они будут похоже, всего вместо case будет if, ну и присвоение чуть по другому.
А между этими двумя реализациями целый диапазон возможных решений.

Цитата(jcxz @ Jul 15 2016, 08:11) *
А если нужен дополнительный индекс, то как потом возвращаться к основному? А если не один уровень вложенности, а больше? Стек хранения состояний городить?

Усложняете. Вот кода, описывающего одно состояние с дополнительными промежуточными состояниями проверки индикации.
Код
void fSelfTest(void)
{    if (old_status-status)
    {    StatusFirstTimeReady("Tst");
        SET_TIMER(N500ms);
    }
    if (event==evTimer)
    {    switch (status_var)
        {    case 0:        OnWorkRed1();     break;
            case 1:        OnChemLed();        break;
            case 2:        OnWaterLed();     break;
            case 3:        ToggleWorkColor();    OffChemWaterLeds();
            case 4:        status=    sWaiting;        break;
            default:    status_var=-1;
        }
        status_var++;
    }
}


Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 15 2016, 07:00
Сообщение #55


Гуру
******

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



QUOTE (Dog Pawlowa @ Jul 15 2016, 09:02) *
Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.

Вот и дошли до того, что при создании реальных автоматов стек состояний (как бы Вы его не назвали другими словами ) тоже можно и нужно использовать. Что тоже уменьшает безмерное разрастание состояний. У меня почти уже в привычке использовать в минимальной "базе" три состояния - текущее, предыдущее и то, на которое сейчас текущее будет измененно. Так же огромное знвчение стека в диагностике работы в РЕАЛЬНЫХ условиях - как дошли до ошибки.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 15 2016, 07:32
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(zltigo @ Jul 15 2016, 10:00) *
е и то, на которое сейчас текущее будет изменено.

А как Вы заглядываете в будущее оперируете с этим значением ?
У меня обычно просто - присвоил текущему и вышел, а анализ смены состояния в начале вызова обработчика автомата.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 15 2016, 08:20
Сообщение #57


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Dog Pawlowa @ Jul 15 2016, 12:02) *
Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.

Конечно ничто не мешает. Только код становится уже плохо читаемым, слишком громоздким с такой реализацией на классических автоматах.
В этом случае я делаю псевдозадачу (которую можно считать к.автоматом). Только она не вытесняется принудительно другими задачами как обычная задача ОС, а вытеснение задачи происходит по логике её работы, при переходе к очередному состоянию автомата. А состояния автомата при этом - это значения PC, которые сохраняются в стеке при вытеснении задачи и на которые происходит переход при активации задачи. И код становится читаемым даже при наличии сложных ветвлений и вложенных состояний автомата.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 15 2016, 08:27
Сообщение #58


Гуру
******

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



QUOTE (Dog Pawlowa @ Jul 15 2016, 10:32) *
А как Вы заглядываете в будущее оперируете с этим значением ?

Хотим изменить текущее состояние автомата - "будущее" это то значение на которое изменим. "Прошлое" это сохраненное котрое было до текущего.
QUOTE
У меня обычно просто - присвоил текущему и вышел...

А присвоение текущему уже в конце обработчика - так и правильнее, ибо состояние сменилось, когда ВСЕ действия сопутствующие смене состояния уже произведены.
Таким образом в процессе переключения типично известны ТРИ состояния прошлое-настояшее-будущее.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
brag
сообщение Sep 7 2016, 23:12
Сообщение #59


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Тоже согласен, что если состояний больше десятка(а зачастую это штук 5) - значит что-то делаете не так. Это касается также и FPGA.
Задачу надо дробить на более простые, а не сливать все в одну кучу. Вот показали бы реальную задачу реализованную на 100 case-aх, я бы показал как ее реализовать гораздо проще.
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 20:47
Рейтинг@Mail.ru


Страница сгенерированна за 0.0219 секунд с 7
ELECTRONIX ©2004-2016