Hallo, bei mir kommt es öfter mal vor, dass ich einen Zustandsautomaten als Funktion erstelle. In der Funktion gibt es dann die static-Zustandsvariable (Enumeration) "zustand". Vor kurzem hatte ich die Herausforderung, dass ich auf einem AVR mehrere Duplikate des Automaten quasiparallel laufen lassen musste. Ich habe das dann so gelöst, dass ich Eingabedaten und Ausgabedaten als Parameter bzw. als Pointer übergeben habe. Außerdem habe ich außerhalb der Funktion "zustand" als Array erstellt und ebenfalls das jeweilige Arrayelement als Zeiger übergeben. Das ganze hat recht gut funktioniert, hatte aber den Nachteil, dass ich zusätzlich mehrere Variablen auch von außen als Zeiger übergeben musste, die ich vor der Instanzierung als static-Variable in der Funktion hatte. Gut, man könnte diese Variablen als Struct zusammenfassen, aber so schön ist das auch nicht. Oder da fällt mir gerade ein, man könnte ja in der Funktion diese Static-Variablen auch als Array definieren. Wie macht Ihr sowas? Vielleicht gibt es komfortablere Lösungen dafür? Danke. Third-Eye
:
Bearbeitet durch User
Third Eye schrieb: > Wie macht Ihr sowas? Den Automaten eintrittsinvariant schreiben und die Zustandsvariable in einer Struktur sammeln und an den Automaten durchreichen. Etwa per Zeiger. > Vielleicht gibt es komfortablere Lösungen dafür? C++, mit allen Vor- und Nachteilen z.B.
Wenn Du "mehrere Instanzen einer Funktion" haben willst, nimm C++ ;-)
Third Eye schrieb: > Gut, man könnte diese Variablen als Struct zusammenfassen, aber so schön > ist das auch nicht. Doch. Genau das ist die Technik. > Oder da fällt mir gerade ein, man könnte ja in der Funktion diese > Static-Variablen auch als Array definieren. Nicht 'in der Funktion'. Ausserhalb. Du hast 'Objekte'. Jedes Objekt besteht aus einer Sammlung aller für diesen Objekttyp relevanten Variablen. In C ist das eben ein struct. Und du hast Methoden, die auf den Objekten arbeiten. In C ist das eben eine Funktion, der du eine struct mitgibst (einen Pointer auf die struct), so dass die Funktion alles hat. Im Grunde ist das schon der erste Schritt in Richtung objektorientierung. > Vielleicht gibt es komfortablere Lösungen dafür? Das ist schon das beste was du kriegen kannst
1 | struct MachineState |
2 | {
|
3 | uint8_t State; |
4 | ....
|
5 | };
|
6 | |
7 | struct MachineState Machines[5] = { .... }; |
8 | |
9 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
|
10 | |
11 | void handleMachine( struct MachineState* pMachine ) |
12 | {
|
13 | switch( pMachine->State ) |
14 | {
|
15 | case .... |
16 | }
|
17 | }
|
18 | |
19 | void work() |
20 | {
|
21 | while( 1 ) |
22 | {
|
23 | for( uint8_t i = 0; i < ARRAY_SIZE(Machines); i++ ) |
24 | handleMachine( &Machines[i] ); |
25 | }
|
26 | }
|
Hat man mehrere unterschiedliche State-Maschinen, die dann auch unterschiedliche Bearbeitungsfunktionen für die Stati brauchen, dann gibt man eben noch einen Funktionspointer mit in die struct hinein. Das wäre dann das Äquivalent dazu, was in C++ zb eine virtuelle Funktion wäre.
:
Bearbeitet durch User
Gibt es wirklich keinen C++ Compiler für deine Plattform, so dass man das 'zu Fuss' erledigen muss?
PittyJ schrieb: > Gibt es wirklich keinen C++ Compiler für deine Plattform, so dass man > das 'zu Fuss' erledigen muss? was ist schlimm daran? Der ganze Linux-Kernel ist in C geschrieben.
PittyJ schrieb: > Gibt es wirklich keinen C++ Compiler für deine Plattform, so dass man > das 'zu Fuss' erledigen muss? So schlimm ist das auch wieder nicht. Ob du das so wie oben in der C Version schreibst, oder so
1 | class MachineState |
2 | {
|
3 | public:
|
4 | ...
|
5 | void handleMachine(); |
6 | |
7 | private:
|
8 | uint8_t State; |
9 | };
|
10 | |
11 | void MachineState::handleMachine() |
12 | {
|
13 | switch( State ) |
14 | {
|
15 | case .... |
16 | }
|
17 | }; |
18 | |
19 | class MachineState Machines[5]; |
20 | |
21 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
|
22 | |
23 | void work() |
24 | {
|
25 | while( 1 ) |
26 | {
|
27 | for( uint8_t i = 0; i < ARRAY_SIZE(Machines); i++ ) |
28 | Machines[i].handleMachine(); |
29 | }
|
30 | }
|
ist erst mal kein so großer Unterschied. Wenn man von der Klasse ableiten kann, sieht die Sache ein wenig anders aus, das ist aber bei so State Maschines grob geschätzt eher selten der Fall.
Peter II schrieb: > was ist schlimm daran? Der ganze Linux-Kernel ist in C geschrieben. Warum Auto fahren? Mit der Pferdekutsche kommt man doch auch ans Ziel. ;-)
Letztendlich macht C++ es ja intern ganz genau so. Jede Objekt-Methode wird einem (im Quelltext nicht sichtbaren) Zeiger auf die Daten des Objektes aufgerufen. Die Funktion MeinGeld.vermehre(100) hat also in Wirklichkeit zwei Parameter, etwa so: vermehre(MeinGeld,100) Man kann das erkennen, wenn man sich den erzeugten Assembler-Code anschaut.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.