Odpowiedzi tutaj wydają się bardzo skomplikowane (ale dokładne, niemniej jednak.) Więc oto moje myśli.
Po pierwsze, podoba mi się dmckee (operacyjna) definicja FSM i ich zastosowanie do programowania.
ma także automat skończony składa się skończonej skończonej liczbie stanów ( znam pedantic, ale), które mogą ogół reprezentowane jako liczba całkowita wartości. W c lub C++ przy użyciu wyliczenia jest bardzo powszechne.
Urządzenie odpowiada na skończoną liczbę wejść , która często może być reprezentowana przez inną zmienną o wartości całkowitej . W bardziej skomplikowanych przypadkach można użyć struktury do reprezentującej stan wejścia.
Każda kombinacja stanu wewnętrznego i wejścia zewnętrznego spowoduje maszynę do:
- ewentualnie przejście do innego stanu
- ewentualnie wygenerować jakiś wynik
więc masz program. Ma stany i jest ich skończona liczba. ("żarówka jest jasna" lub "żarówka jest słaba" lub "żarówka jest wyłączona." 3 stany skończone.) Twój program może być tylko w jednym stanie na raz.
Powiedzmy, że chcesz, aby twój program zmieniał stany. Zazwyczaj będziesz potrzebować czegoś, aby stało, aby wywołać zmianę stanu. W tym przykładzie, w jaki sposób możemy wziąć dane wejściowe użytkownika, aby określić stan - powiedzmy, naciśnij klawisz.
Możesz chcieć takiej logiki. Gdy użytkownik naciśnie klawisz:
- Jeśli żarówka jest "wyłączona", należy ją "przyciemnić".
- Jeśli żarówka jest "słaba", żarówka powinna być "jasna".
- Jeśli żarówka jest "jasna", włącz żarówkę "off".
Oczywiście, zamiast "zmieniać żarówkę", można "zmieniać kolor tekstu" lub cokolwiek program ten musi wykonać. Zanim zaczniesz, będziesz chciał zdefiniować swoje stany.
Więc patrząc na niektóre kodu pseudoish C:
/* We have 3 states. We can use constants to represent those states */
#define BULB_OFF 0
#define BULB_DIM 1
#define BULB_BRIGHT 2
/* And now we set the default state */
int currentState = BULB_OFF;
/* now we want to wait for the user's input. While we're waiting, we are "idle" */
while(1) {
waitForUserKeystroke(); /* Waiting for something to happen... */
/* Okay, the user has pressed a key. Now for our state machine */
switch(currentState) {
case BULB_OFF:
currentState = BULB_DIM;
break;
case BULB_DIM:
currentState = BULB_BRIGHT;
doCoolBulbStuff();
break;
case BULB_BRIGHT:
currentState = BULB_OFF;
break;
}
}
I voila. Prosty program, który zmienia stan.
Ten kod wykonuje tylko niewielką część instrukcji switch
- w zależności od bieżącego stanu bieżącego. Następnie ten stan jest aktualizowany. Tak działają FSM.
Teraz oto kilka rzeczy, które możesz zrobić:
Oczywiście, ten program po prostu zmienia zmienną currentState
. Będziesz chciał, aby twój kod zrobił coś bardziej interesującego przy zmianie stanu. Funkcja doCoolBulbStuff()
może, nie wiem, umieścić zdjęcie żarówek na ekranie. Lub coś.
Ten kod wyszukuje tylko naciśnięcie klawisza. Ale twój FSM (a tym samym twoja instrukcja przełączania) może wybrać stan w oparciu o to, co użytkownik wprowadził (np. "O" oznacza "idź do wyłączenia", a nie po prostu przejdź do następnego elementu w sekwencji.)
Część pytania dotyczyła struktury danych.
Jedna osoba zasugerowała użycie enum
do śledzenia stanów. Jest to dobra alternatywa dla #defines
, której użyłem w moim przykładzie. Ludzie sugerują również tablice - i te tablice śledzą przejścia między stanami. Jest to również doskonała struktura do użycia.
Biorąc pod uwagę powyższe, można użyć dowolnej struktury (coś podobnego do drzewa, tablicy, czegokolwiek), aby śledzić poszczególne stany i określić, co należy zrobić w każdym stanie (stąd niektóre sugestie użyj "wskaźników funkcji" - mapuj stan do wskaźnika funkcji, który wskazuje, co zrobić w tym stanie.)
Nadzieję, że pomaga!
Być może zainteresuje Cię Ragel (http://www.complang.org/ragel/), który jest kompilatorem maszyny stanu, który może generować kod C. Jeśli nie spełnia twoich celów, być może wygenerowany kod jest interesujący. – sris
powiązane http://stackoverflow.com/questions/1647631/c-state-machine-design/1651187 – jldupont