учебные руководства по конечным автоматам [закрываются]

Единственная вещь, которую делает установка, создает ярлык на игры. Игры являются играми браузеров, таким образом, никакая установка не необходима.

Вот ссылки:

Команда и Завоевывают

лорд Ultima

68
задан paradigmatic 25 November 2012 в 14:59
поделиться

7 ответов

Конечные автоматы очень просты в 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;
}

Я не помещаю функцию lookup_transitions () , поскольку она тривиальна .

Так я годами делаю конечные автоматы.

124
ответ дан 24 November 2019 в 14:07
поделиться

Конечные автоматы не являются чем-то, что по своей сути требует объяснения или даже использования учебника. Я предлагаю вам взглянуть на данные и на то, как они должны быть проанализированы.

Например, мне пришлось проанализировать протокол данных для компьютера полета воздушного шара ближнего космоса , он хранил данные на SD-карте в определенном формате (двоичном), который необходимо было преобразовать в файл, разделенный запятыми. Использование конечного автомата для этого имеет наибольший смысл, потому что в зависимости от того, какой будет следующий бит информации, нам нужно изменить то, что мы анализируем.

Код написан с использованием C ++ и доступен как ParseFCU . Как вы можете видеть, он сначала определяет, какую версию мы анализируем, и оттуда он входит в два разных конечных автомата.

Он входит в конечный автомат в заведомо исправном состоянии, в этот момент мы начинаем синтаксический анализ и в зависимости от того, с какими персонажами сталкиваемся, мы либо переходим к следующему состоянию, либо возвращаемся в предыдущее состояние. Это в основном позволяет коду самостоятельно адаптироваться к способу хранения данных и к тому, существуют ли какие-либо данные вообще.

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

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

Это в основном позволяет коду самостоятельно адаптироваться к способу хранения данных и к тому, существуют ли какие-то данные вообще.

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

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

Это в основном позволяет коду самостоятельно адаптироваться к способу хранения данных и к тому, существуют ли какие-либо данные вообще.

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

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

9
ответ дан 24 November 2019 в 14:07
поделиться

Я тестирую модуль только код, который я ' м не уверен насчет. Конечно - никогда не знаешь, что нанесет тебе удар, но написание тестов на тривиальные вещи кажется мне излишним.

Я не гуру модульного тестирования / tdd - но я думаю, что это нормально, если вы НЕ пишете тесты только для того, чтобы иметь их. Они должны быть полезны. Если у вас достаточно опыта в модульном тестировании - вы начнете почувствовать , когда они будут полезными, а когда нет.

Вам может понравиться эта книга .

Изменить:
На самом деле - я только что нашел цитату об этой главе под главой, посвященной изоляционным каркасам. Речь идет о переопределении тестов (один конкретный тест), но я думаю, что идея остается в более глобальном масштабе: ломается даже при малейших изменениях кода, даже если общая функциональность по-прежнему работает. Считайте это более техническим способом не проверять правильные вещи. Тестирование взаимодействий - это обоюдоострый меч: слишком много проверяйте, и вы начинаете терять из виду общую картину - общую функциональность; проверить это слишком мало, и вы пропустите Лично я предпочитаю табличный подход, но они, безусловно, имеют свои достоинства, широко используются и могут быть эффективными, особенно для более простых автоматов.

Одна такая структура описана Стивом Рабином в «Жемчужины программирования игр», глава 3.0. (Разработка общей надежной системы ИИ) .

Подобный набор макросов обсуждается здесь:

Если вас также интересуют реализации конечного автомата C ++, можно найти гораздо больше. Я отправлю указатели, если вам интересно.

0 (Разработка общего надежного движка AI) .

Подобный набор макросов обсуждается здесь:

Если вас также интересуют реализации конечного автомата C ++, можно найти гораздо больше. Я отправлю указатели, если вам интересно.

0 (Разработка общего надежного движка AI) .

Аналогичный набор макросов обсуждается здесь:

Если вас также интересуют реализации конечного автомата C ++, можно найти гораздо больше. Я отправлю указатели, если вам интересно.

9
ответ дан 24 November 2019 в 14:07
поделиться

Объектно-ориентированное моделирование в реальном времени было фантастическим (опубликовано в 1994 году и сейчас продается всего за 81 цент плюс 3,99 доллара за доставку).

4
ответ дан 24 November 2019 в 14:07
поделиться

Это все, что вам нужно знать.

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;
    }
}
3
ответ дан 24 November 2019 в 14:07
поделиться

Есть много уроков по изучению ручного создания конечных автоматов на C, но позвольте мне также предложить компилятор конечных автоматов Ragel:

http://www.complang.org/ragel/

Это довольно простой способ определения конечных автоматов, а затем вы можете генерировать графики, генерировать код в разных стилях (управляемый таблицами, управляемый goto), анализировать этот код, если хотите, и т. д. И он мощный, может использоваться в производственном коде для различных протоколов.

3
ответ дан 24 November 2019 в 14:07
поделиться

Я предпочитаю использовать указатели на функции, а не гигантские операторы 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);
}
28
ответ дан 24 November 2019 в 14:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: