A állapotgépek (véges automaták) kézenfekvő megvalósítása a táblázatos megvalósítás, melynek lényege, hogy a pillanatnyi állapottól és az aktuális inputtól függően elővesszük egy táblázatból az új állapotot és az állapotátmenethez tartozó tevékenységet megvalósító függvény címét, amit végrehajtunk. Ezzel állapotgépünk algoritmusa így nézhet ki:
```
while (van_input) {
új_állapot = állapot_tábla[akt_állapot][input]
tevékenység = [akt_állapot][input]
tevélenység_vegrehajtása
akt_állapot = új_allapot
}
while (van_input) {
új_állapot = állapot_tábla[akt_állapot][input]
tevékenység = [akt_állapot][input]
tevélenység_vegrehajtása
akt_állapot = új_allapot
}
```
Így egy konkrét feladat (pl. ly számláló) implementálása csak a két táblázat megfelelő kitöltéséből áll, feltételezve, hogy mind az állapotokat, mind az inputot olyan módon kódoljuk, hogy azzal az adott nyelven lehet táblázatot (tárolót) indexelni. C nyelven az integrál típussal lehet indexelni. C++-ban már más a helyzet (ld. asszociatív tárolók).
A táblázatok (lehet összevont táblázat is) kitöltését segítheti valamilyen generátor, ekkor annak mérete nem nagyon érdekes, de lehet, hogy kézzel töltjük ki, ekkor érdemes a táblázat méretét csökkenteni. A legkézenfekvőbb csökkentési lehetőség, az állapotok összevonása és az inputot csoportokra bontása (ld. ly számláló példa).
...
...
@@ -29,6 +29,7 @@ class Allapotgep {
```
Az állapotgép a genetika szorgalmihoz viszonyítva a template paraméterezés mellett az alábbiakban tér el:
* minden állapotátmenetkor végrehajt egy akciót;
* tárolja a bevezetőben említett 2D táblázatban a következő állapotot és az akciót.
...
...
@@ -39,7 +40,6 @@ struct Nop {
/// következő állapot
Allkov_allapot;
Nop(Allkov_all):kov_allapot(kov_all){}
/// ha az állapotgép ebbe az állapotba ér, meghívja ezt a függvényt
/// @param ch - erre az input értékre léptünk ide
virtualvoidakcio(Tch){}
...
...
@@ -50,7 +50,7 @@ struct Nop {
A 2D táblázathoz egy olyan osztályt definiáltunk, ami az All és Imp sablonparaméterként megadott típusokkal indexelhető, és törli a tárol elemeket, ha elérkezett az idő.
@@ -96,7 +96,7 @@ class Lyszaml : public Allapotgep<LyAllapot, LyInput, char> {
//...
};//lyszamlalo.hpp
```
_Megjegyzés: a template paraméterek miatt nyugodtan használhattunk volna az enum-ok vagy akár a char helyett egy szimpla osztályt is. Így akár komplikáltabb logika is beépíthető._
_Megjegyzés: a template paraméterek miatt nyugodtan használhattunk volna az enum-ok vagy akár a char helyett egy szimpla osztályt is. Így akár komplikáltabb logika is beépíthető._
Az egyes állapotokhoz kapcsolódó akciókat a következő módon definiáljuk:
A bemenetet input csoportokká alakító függvény `Lyszamlalo` esetén magyarázatra nem szorul:
A bemenetet input csoportokká alakító függvény `Lyszamlalo` esetén. Magyarázatra nem szorul:
```c++
LyInputinput(charch)const{
if(ch=='l')returnLyInput::l;
...
...
@@ -148,7 +148,7 @@ Az `Lyszamlalo` **get()** függvénye visszaadja a megtalált _ly_-ok számát.
## Feladatok
### Kommentezés
A mintapélda lapján hozz létre egy `Komment` osztályt, ami a bemenetére érkező szabályos C programból kiszűri a /* ... */ alakú kommenteket! Feltételezzük, hogy szövegkonstansban nem szerepel "/\*", ill. "\*/" karaktersorozat. A megszűrt, komment nélküli programot az osztály **std::string get()** tagfüggvényével lehet lekérdezni.
A mintapélda alapján hozz létre egy `Komment` osztályt, ami a bemenetére érkező szabályos C programból kiszűri a /* ... */ alakú kommenteket! Feltételezzük, hogy szövegkonstansban nem szerepel "/\*", ill. "\*/" karaktersorozat. A megszűrt, komment nélküli programot az osztály **std::string get()** tagfüggvényével lehet lekérdezni.
Nézd meg a _main.cpp_-ben lévő teszteket, állítsd az _ELKESZULT_ makrót 1-re és próbáld megoldani a feladatot. A megoldás során a *komment.hpp* és *komment.cpp* fájlokban dolgozz!