учебные пособия по государственным машинам [закрыто]
Мне просто интересно, знает ли кто-нибудь о некоторых хороших учебниках в Интернете для разработки государственных машин. Или электронные книги?
Я начинаю работать на государственных машинах и просто нужно что-то общее, чтобы меня начали.
8 ответов:
состояние машины очень просты в C, если вы используете указатели на функции.
в основном вам нужно 2 массива-один для указателей функций состояния и один для правил перехода состояния. Каждая функция состояния возвращает код, вы просматриваете таблицу перехода состояния по состоянию и возвращаете код, чтобы найти следующее состояние, а затем просто выполняете его.
int entry_state(void); int foo_state(void); int bar_state(void); int exit_state(void); /* array and enum below must be in sync! */ int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state}; enum state_codes { entry, foo, bar, end}; enum ret_codes { ok, fail, repeat}; struct transition { enum state_codes src_state; enum ret_codes ret_code; enum state_codes dst_state; }; /* transitions from end state aren't needed */ struct transition state_transitions[] = { {entry, ok, foo}, {entry, fail, end}, {foo, ok, bar}, {foo, fail, end}, {foo, repeat, foo}, {bar, ok, end}, {bar, fail, end}, {bar, repeat, foo}}; #define EXIT_STATE end #define ENTRY_STATE entry int main(int argc, char *argv[]) { enum state_codes cur_state = ENTRY_STATE; enum ret_codes rc; int (* state_fun)(void); for (;;) { state_fun = state[cur_state]; rc = state_fun(); if (EXIT_STATE == cur_state) break; cur_state = lookup_transitions(cur_state, rc); } return EXIT_SUCCESS; }
Я не ставлю
Я предпочитаю использовать указатели функций над гигантскими
switch
заявления, но в отличие от ответ qrdl обычно я не использую явные коды возврата или таблицы переходов.кроме того, в большинстве случаев вам понадобится механизм для передачи дополнительных данных. Вот пример государственной машины:
#include <stdio.h> struct state; typedef void state_fn(struct state *); struct state { state_fn * next; int i; // data }; state_fn foo, bar; void foo(struct state * state) { printf("%s %i\n", __func__, ++state->i); state->next = bar; } void bar(struct state * state) { printf("%s %i\n", __func__, ++state->i); state->next = state->i < 10 ? foo : 0; } int main(void) { struct state state = { foo, 0 }; while(state.next) state.next(&state); }
государственные машины-это не то, что по своей сути требует объяснения или даже использования учебника. Я предлагаю вам взглянуть на данные и как они должны быть проанализированы.
например, мне пришлось разобрать протокол данных для рядом с космическим воздушным шаром полета компьютера, он хранил данные на SD-карте в определенном формате (двоичном), который необходимо было разобрать в файл, разделенный запятыми. Использование государственной машины для этого имеет наибольший смысл, потому что в зависимости на какой следующий бит информации нам нужно изменить то, что мы анализируем.
код написан с использованием C++, и доступен как ParseFCU. Как вы можете видеть, он сначала определяет, какую версию мы анализируем, и оттуда он входит в два разных состояния машины.
Он входит в конечный автомат в известном хорошем состоянии, в этот момент мы начинаем разбор и в зависимости от того, с какими символами мы сталкиваемся, мы либо переходим к следующему состоянию, либо возвращаемся к предыдущему государство. Это в основном позволяет коду самостоятельно адаптироваться к способу хранения данных и независимо от того, существуют ли определенные данные вообще.
в моем примере строка GPS не является обязательным требованием для регистрации полетного компьютера, поэтому обработка строки GPS может быть пропущена, если найдены конечные байты для этой записи в один журнал.
государственные машины просты в написании, и в целом я следую правилу, что он должен течь. Входной сигнал идя через систему должен пропустить с определенная легкость от государства к государству.
к сожалению, большинство статей о машинах состояний написаны для C++ или других языков, которые имеют прямую поддержку полиморфизма, поскольку приятно моделировать состояния в реализации FSM как классы, производные от абстрактного класса состояния.
тем не менее, довольно легко реализовать машины состояний в C, используя либо операторы switch для отправки событий в состояния (для простых FSMs они в значительной степени кодируют прямо), либо используя таблицы для отображения событий в состояние переходы.
здесь есть пара простых, но достойных статей по базовой структуре для государственных машин в C:
- http://www.gedan.net/2008/09/08/finite-state-machine-matrix-style-c-implementation/
- http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
Edit: сайт "на обслуживании" , веб-архив ссылки:
- http://web.archive.org/web/20160517005245/http://www.gedan.net/2008/09/08/finite-state-machine-matrix-style-c-implementation
- http://web.archive.org/web/20160808120758/http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
switch
машины состояний на основе операторов часто используют набор макросов, чтобы "скрыть" механикуswitch
оператор (или использовать наборif
/then
/else
заявления вместоswitch
) и сделать то, что составляет "язык FSM" для описания государственной машины в источнике C. Я лично предпочитаю табличный подход, но они, безусловно, имеют свои достоинства, широко используются и могут быть эффективными, особенно для более простых FSMs.одна из таких рамок изложена Стивом Рабином в "игровое Программирование драгоценных камней" глава 3.0 (проектирование общего надежного ИИ Двигатель).
подобный набор макросов обсуждается здесь:
если вы также заинтересованы в реализациях c++ state machine, можно найти гораздо больше. Я буду размещать указатели, если вам интересно.
Объектно-Ориентированное Моделирование В Реальном Времени было фантастическим (опубликовано в 1994 году и теперь продается всего за 81 цент, плюс $3.99 доставка).
есть много уроков, чтобы узнать ручной работы государственных машин в C, но позвольте мне также предложить ragel state machine compiler:
http://www.complang.org/ragel/
Он имеет довольно простой способ определения состояния машин, а затем вы можете генерировать графики, генерировать код в разных стилях (табличный, Гото-управляемый), анализировать этот код, если вы хотите, и т. д. И это мощный, может быть использован в производственном коде для различных протоколов.
Это все, что нужно знать.
int state = 0; while (state < 3) { switch (state) { case 0: // Do State 0 Stuff if (should_go_to_next_state) { state++; } break; case 1: // Do State 1 Stuff if (should_go_back) { state--; } else if (should_go_to_next_state) { state++; } break; case 2: // Do State 2 Stuff if (should_go_back_two) { state -= 2; } else if (should_go_to_next_state) { state++; } break; default: break; } }
государственные машины могут быть очень сложными для сложной задачи. Они также подвержены неожиданным ошибкам. Они могут превратиться в кошмар, если кто-то сталкивается с ошибкой или нуждается в изменении логики в будущем. Их также трудно отслеживать и отлаживать без диаграммы состояния. Структурированное Программирование намного лучше (например, вы, вероятно, не будете использовать конечный автомат на уровне магистрали). Вы можете использовать структурированное Программирование даже в контексте прерывания (где находятся конечные автоматы обычно используемый.) Смотрите эту статью "макросы для имитации многозадачности/блокировки кода на уровне прерывания" найдено по адресу codeproject.com.