Frage

Ich frage mich, ob jemand weiß von einigen guten Tutorials im Internet für Zustandsmaschinen zu entwickeln. Oder E-Books?

Ich beginne auf Zustandsmaschinen arbeiten und brauchen nur etwas Allgemeines mich zu beginnen.

War es hilfreich?

Lösung

Zustandsmaschinen sind sehr einfach in C, wenn Sie Funktionszeiger verwenden.

Grundsätzlich benötigen Sie 2-Arrays - eine für Zustand Funktionszeiger und einen für Regeln Zustandsübergang. Jeder Staat Funktion gibt den Code, Sie Lookup-Zustandsübergangstabelle von Staat und Rückkehrcode den nächsten Zustand zu finden und dann einfach durchführen.

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

ich nicht lookup_transitions() Funktion setzen, wie es trivial ist.

Das ist die Art, wie ich tue Zustandsmaschinen seit Jahren.

Andere Tipps

ich bevorFunktionsZeiger über gigantische switch-Anweisungen, aber im Gegensatz zu qrdl Antwort ich normalerweise nicht explizit Rückgabecodes oder Übergangstabellen verwenden.

Auch in den meisten Fällen werden Sie einen Mechanismus entlang zusätzlichen Daten übergeben werden sollen. Hier ist ein Beispiel Zustandsmaschine:

#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);
}

Zustandsmaschinen sind nicht etwas, das von Natur aus einem Tutorial erklärt werden muss oder sogar verwendet. Was ich vorschlagen, dass Sie einen Blick auf die Daten nehmen und wie es muss analysiert werden.

Zum Beispiel hatte ich das Datenprotokoll für ein Nahraum Ballonflugcomputer zu analysieren , sie gespeicherten Daten auf der SD-Karte in einem bestimmten Format (binär), die in eine durch Komma getrennt Datei analysiert out benötigt werden. eine Zustandsmaschine für diese Verwendung von am meisten Sinn macht, weil je nachdem, was das nächste Bit von Informationen müssen wir ändern, was wir parsen.

Der Code wird unter Verwendung von C ++ geschrieben und ist als ParseFCU . Wie Sie sehen können, ist es zunächst erkennen, welche Version wir parsen, und von dort geht es zwei verschiedene Zustandsmaschinen.

Es gibt die Zustandsmaschine in einem bekannten Zustand, an diesem Punkt beginnen wir das Parsen und je nachdem, was Charaktere, die wir begegnen uns entweder Schachzug in den nächsten Zustand oder in einen früheren Zustand zurückgehen. Auf diese Weise kann im Grunde der Code auf den Weg zur Selbst anpassen die Daten gespeichert sind und ob bestimmte Daten existieren überhaupt noch.

In meinem Beispiel der GPS-String ist keine Voraussetzung für die Flugcomputer zu protokollieren, so dass die Verarbeitung des GPS-String übersprungen werden kann, wenn die Endung Bytes für die einzelnen Protokollschreib gefunden wird.

Zustandsmaschinen sind einfach zu schreiben, und im Allgemeinen Ich folge der Regel, dass es fließen sollte. Eingang durch das System gehen sollte fließen mit gewisser Leichtigkeit von Staat zu Staat.

Leider sind die meisten Artikel auf Zustandsmaschinen für C ++ geschrieben oder andere Sprachen, die für Polymorphismus, wie es ist schön, ein direkte Unterstützung haben die Zustände in einer FSM Implementierung als Klassen zu modellieren, die von einer abstrakten Zustandsklasse abgeleitet werden.

Allerdings ist es ziemlich einfach, Zustandsmaschinen in C entweder mit Switch-Anweisungen zum Versand Ereignisse Staaten (für einfache FSMs, sie ziemlich viel Code rechts oben) oder mit Hilfe von Tabellen abzubilden Ereignisse Zustandsübergänge zu implementieren.

Es gibt ein paar einfachen, aber anständigen Artikel auf einem Grundgerüst für die Zustandsmaschinen in C hier:

Real-Time objektorientierte Modellierung fantastisch war (im Jahr 1994 veröffentlicht und jetzt so wenig wie 81 Cent zu verkaufen, und 3,99 Versand $).

Das ist alles, was Sie wissen müssen.

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

Es gibt eine Menge von Lektion handcrafting Zustandsmaschinen in C zu lernen, aber lassen Sie mich auch Ragel Zustandsmaschine Compiler vorschlagen:

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

Es hat ganz einfache Art und Weise Zustandsmaschinen zu definieren und dann können Sie Diagramme generieren, erzeugen Code in verschiedenen Stilen (tabellengesteuerte, gehe gesteuert), dass Code zu analysieren, wenn Sie wollen, etc. Und es ist mächtig, kann sein in Produktionscode für verschiedene Protokolle verwendet.

Zustandsmaschinen können für ein komplexes Problem sehr komplex sein. Sie unterliegen auch unerwartete Fehler. Sie können in einen Albtraum verwandeln, wenn jemand in einen Fehler läuft oder muss die Logik in der Zukunft ändern. Sie sind auch schwer zu folgen und zu debuggen, ohne das Zustandsdiagramm. Strukturierte Programmierung ist viel besser (zum Beispiel würden Sie wahrscheinlich nicht eine Zustandsmaschine auf Fern Ebene verwenden). Sie können strukturierte Programmierung verwenden, auch im Interrupt-Kontext (wo Zustandsmaschinen in der Regel verwendet werden). Lesen Sie diesen Artikel "Makros zu simulieren multi- Tasking / Sperrcode auf Interrupt-Ebene " bei codeproject.com gefunden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top