Forum: PC-Programmierung Zwei Stufige State Machine in C


von Christian R. (cris06)


Lesenswert?

Hallo,

ich möchte gerne eine zwei stufige State Machine zu programmieren. Nur 
ist mir noch nicht ganz klar, wie ich es anstelle. Das ganze soll in 
einer klassischen Zeitscheiben-Scheduler laufen. Die State Machine merkt 
sich dabei die zuletzt ausgeführte Operation.

Das ganze ist zwei Stufig.
1. Stufe : 4 Zusände
2. Stufe : Je ca. 10 Zusände

Bisher habe ich die States in einem eigenem enum angelegt und gemerkt. 
Aber irgendwie wird das zu unübersichtlich / umständlich.
1
enum{
2
 STATE_1,
3
 STATE_2,
4
 STATE_3
5
}state
6
7
enum{
8
 STATE1_1,
9
 STATE1_2,
10
 STATE1_3,
11
...
12
}state1
13
14
enum{
15
 STATE2_1,
16
 STATE2_2,
17
 STATE2_3,
18
...
19
}state2

Hier mal exemplarisch dargestellt.
Wie kann man das besser lösen?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Christian R. schrieb:
> Das ganze ist zwei Stufig.
> 1. Stufe : 4 Zusände
> 2. Stufe : Je ca. 10 Zusände

> Wie kann man das besser lösen?

Besser Namen wählen ;-) Scherz beiseite. Wenn Du wirklich 40 
verschiedene Zustände hast, und die Unterzustände für jeden der 4 
Zustände unterschiedlich sind, dann würde ich eine enum für den 
Haupzustand wählen und 4 enums für die Unterzustände. Einfach wird es 
nicht werden.

Evtl. versuchst Du aber auch mehr als einen Automaten in einem 
abzubilden?

mfg Torsten

von Wilhelm M. (wimalopaan)


Lesenswert?

Die Antwort ist Kapselung. Und das erreichst Du besser mit C++ als mit 
C. Ich würde mal drüber nachdenken ...

von Nop (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Die Antwort ist Kapselung.

Kann man in C wunderbar machen.

> Und das erreichst Du besser mit C++

GLeich in der 2. Antwort mit C++-Getrolle offtopic geworden - reife 
Leistung.

von Theor (Gast)


Lesenswert?

Das primäre Problem scheint mir zunächst nicht-technischer Art zu sein.

Bei Problemen, gleich welcher Art, sollte man aufmerken, wenn man Wörter 
wie "irgendwie" zur Beschreibung benutzt. Es hilft dann weiter, wenn man 
sie durch präzise Adjektive ersetzt. Man kann sich Wie-fragen stellen, - 
etwa: Wie, wann, wodurch etcpp. -, um das zu erreichen.

Das Ergebnis enthält meist schon Hinweise auf die Antwort.

von A. S. (Gast)


Lesenswert?

Wenn die jeweils 10 Unterzustände irgendwie ähnlich sind, kannst Du sie 
"mergen", also eine Obermenge bilden (sind dann vielleicht 15, wovon 
nicht alle in jedem Hauptstate vorkommen).

Wenn die jeweils 10 Unterzustände verschieden sind, und innerhalb eines 
Hauptzustandes beliebig angewählt werden, dann gilt:

Torsten R. schrieb:
> dann würde ich eine enum für den Haupzustand wählen
> und 4 enums für die Unterzustände. Einfach wird es nicht werden.

Wenn die jeweils 10 Unterzustände ausschließlich sequentielle 
abgearbeitet werden, dann gäbe es die Möglichkeit mit reinen Zahlen, 
also:
1
/* all 10 state defined explicit and unconditional increment */
2
{
3
   switch(sub_state)
4
   {
5
   case 0: /* do whatever to do in first state */
6
           break;
7
   case 1: /* do whatever to do in second state */
8
           break;
9
           ...
10
   case 9:/* ... */
11
           break;
12
   default:/* flag error */
13
           flag_error(sub_state);
14
           sub_state = 0;
15
           break;
16
   }
17
   if(sub_state < 9) {sub_state++;}
18
   else              {sub_state=0;}
19
}
20
21
/* set of states, 10 Maximum */
22
{
23
   switch(sub_state)
24
   {
25
   case 0: /* do whatever to do in first state */
26
           sub_state++; /* unconditional next state */
27
           break;
28
   case 1: /* do whatever to do in second state */
29
           if(...) {sub_state++;} /* with condition */
30
           break;
31
           ...
32
   case 9:/* ... */
33
           sub_state++;
34
           break;
35
   default:/* skip this one or set to 0 */
36
           if(sub_state <9) {sub_state++;}
37
           else             {sub_state=0;}
38
           break;
39
   }
40
}

Das ist aber nicht wirklich schön!
Macht aber manchmal Sinn, wenn man nur irgendwie 10 Dinge nacheinander 
machen möchte...

von Wilhelm M. (wimalopaan)


Lesenswert?

Nop schrieb:
> Wilhelm M. schrieb:
>> Die Antwort ist Kapselung.
>
> Kann man in C wunderbar machen.
>
>> Und das erreichst Du besser mit C++
>
> GLeich in der 2. Antwort mit C++-Getrolle offtopic geworden - reife
> Leistung.

Das war ja wieder klar:
der TO stellt eine Frage wie: ich möchte mit der Nagelfeile einen Nagel 
in die Wand schlagen, und Du antwortest ihm, dass das gut geht und er 
die Feile nur am richtigen Ende anfassen muss.
Ich aber antworte ihm: nimm lieber einen Hammer.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Wilhelm M. schrieb:

> Das war ja wieder klar:
> der TO stellt eine Frage wie: ich möchte mit der Nagelfeile einen Nagel
> in die Wand schlagen, und Du antwortest ihm, dass das gut geht und er
> die Feile nur am richtigen Ende anfassen muss.
> Ich aber antworte ihm: nimm lieber einen Hammer.

Ich bin ja auch ein großer Fan von C++. Aber: Der TO hat explizit C in 
der Überschrift erwähnt und evtl. hat er auch einfach seine Gründe, 
warum er C verwendet.

P.S: Nicht alles was hinkt ist ein Vergleich!

von Der Andere (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Ich aber antworte ihm: nimm lieber einen Hammer.

Nein, du behauptest es muss ein 600g Hammer sein. Dabei gibt es Nägel 
die mit einem 400 oder 300g Hammer viel besser einzuschlagen sind.
Wer eine State machine nicht in C hinkriegt, der kriegt sie mit C++ 
schon gar nicht hin.
Du bist derjenige der meint jeder müsste genau dein präferiertes 
Werkzeug benutzen, dabei ist das Problem des TO viel tiefgreifender.

Die Organsisation seiner States dürfte das kleinste Problem sein wenn 
man 2 verschachtelte State-machines mit 4 x 10 States meint bauen zu 
müssen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Torsten R. schrieb:
> Wilhelm M. schrieb:
>
>> Das war ja wieder klar:
>> der TO stellt eine Frage wie: ich möchte mit der Nagelfeile einen Nagel
>> in die Wand schlagen, und Du antwortest ihm, dass das gut geht und er
>> die Feile nur am richtigen Ende anfassen muss.
>> Ich aber antworte ihm: nimm lieber einen Hammer.
>
> Ich bin ja auch ein großer Fan von C++. Aber: Der TO hat explizit C in
> der Überschrift erwähnt und evtl. hat er auch einfach seine Gründe,
> warum er C verwendet.

Einer der Gründe könnte sein, dass er es aus Unwissenheit nicht in 
Betracht gezogen hat, oder er ggf. nicht weiß, wie er Sprachen wie C, 
C++, Java, etc. mischen kann, ...

von Wilhelm M. (wimalopaan)


Lesenswert?

Der Andere schrieb:
> Wilhelm M. schrieb:
>> Ich aber antworte ihm: nimm lieber einen Hammer.
>
> Nein, du behauptest es muss ein 600g Hammer sein. Dabei gibt es Nägel
> die mit einem 400 oder 300g Hammer viel besser einzuschlagen sind.
> Wer eine State machine nicht in C hinkriegt, der kriegt sie mit C++
> schon gar nicht hin.

Das wiederum glaube ich nicht: da viele Leute es auf einem höheren 
Abstraktionsniveau nachweislich besser schaffen als low-level, liegt 
auch hier die Vermutung nahe. C++ war auch mehr pars pro toto, gemeint 
war mehr OOD.

> Du bist derjenige der meint jeder müsste genau dein präferiertes
> Werkzeug benutzen, dabei ist das Problem des TO viel tiefgreifender.

Gar nicht. Ich schrieb, er können mal darüber nachdenken ;-)

von Nop (Gast)


Lesenswert?

Wilhelm M. schrieb:
> C++ war auch mehr pars pro toto, gemeint war mehr OOD.

Schon wieder Bullshit. Man kann Statemachines problemlos in C machen. 
OOD ist dafür schlichtweg überflüssiges Spielzeug, genau wie C++.

von Nop (Gast)


Lesenswert?

Christian R. schrieb:

> Hier mal exemplarisch dargestellt.
> Wie kann man das besser lösen?

Indem man sich erstmal Gedanken um ein Design macht. 4x10 Zustände, die 
"irgendwie" gekoppelt sind, werden immer zu häßlichem Chaos führen.

Da Du zur Problemstellung an sich nichts sagst, werden konkrete Hinweise 
schwierig. Eine zweistufige Statemachine würde man aber normalerweise so 
machen, daß man eine high-level-statemachine hat, mit 4 Zuständen. Diese 
ruft dann in jedem Zustand genau einen der low-level-Automaten auf (die 
mit 10 Zuständen).

Entscheidend ist, daß die low-level-Automaten voneinander nichts wissen 
und auch keine Ergebnisse teilen.

Wenn das nicht möglich ist: Problem neu analysieren.

von Mikro 7. (mikro77)


Lesenswert?

Wenn der TS mit symbolische Namen arbeiten will, die auch ("öffentlich") 
sichtbar sind (also potentiell kollidieren), dann bietet C++ mit 
Namespaces schon einen Vorteil.

Ansonsten sind 40 Zustände aber auch noch nicht soo kompliziert. Ein 
zentrales gut dokumentiertes Modul für die Funktionseinsprünge in der 
Art von Achims Vorschlag ist ok, denke ich.

Das ist aber nur die halbe Miete. Interessant wird die Beschreibung der 
Zustandsübergänge (wenn es denn tatsächlich eine State Machine ist und 
nicht nur Save Points). Damit man sich (auch noch nach ein paar Monaten) 
zurecht findet, gibt es imho keine Alternative zu einer grafischen 
Dokumentation (oder zumindest eine Tabelle).

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Wilhelm M. schrieb:
> da viele Leute es auf einem höheren
> Abstraktionsniveau nachweislich besser schaffen als low-level, liegt
> auch hier die Vermutung nahe

Ist das Deine Erfahrung oder kannst Du das irgendwie belegen?

Dass die allermeisten Statemachines von 4*10 auch verkleinert werden 
können (ggf. zum Preis der Unleserlichkeit), geschenkt. Aber warum das 
in OOP besser geht als mit Papier und Bleistift, UML oder C, ist wohl 
nur dem klar, der OOP besser kann als eines der anderen.

von good coding (Gast)


Lesenswert?

Christian R. schrieb:
> Aber irgendwie wird das zu unübersichtlich / umständlich.

Lager die einzelnen Automaten in einzelne Module aus. Dann bleibt es 
übersichtlich.

von Wilhelm M. (wimalopaan)


Lesenswert?

Achim S. schrieb:
> Wilhelm M. schrieb:
>> da viele Leute es auf einem höheren
>> Abstraktionsniveau nachweislich besser schaffen als low-level, liegt
>> auch hier die Vermutung nahe
>
> Ist das Deine Erfahrung oder kannst Du das irgendwie belegen?

Ich kann Dir natürlich keine Studie darüber liefern, die das belegt.

Allerdings habe ich die Erfahrung gemacht, dass ein deklarativer Ansatz 
oft anderen Personen leichter zu vermitteln ist als ein prozeduraler. In 
diesem Beispiel heißt das, dass man die Zustandsübergänge abstrakt (ggf. 
durch eine DESL) beschreibtohne sie im Code zu "verstecken".
Das ist vergleichbar mit deklarativen UI Beschreibungen. Das können auch 
Personen, die wenig von der Technik wissen.

von Nop (Gast)


Lesenswert?

Wilhelm M. schrieb:

> diesem Beispiel heißt das, dass man die Zustandsübergänge abstrakt (ggf.
> durch eine DESL) beschreibtohne sie im Code zu "verstecken".

In diesem Beispiel ist das Problem doch eher, daß es kein Design zu 
geben scheint, bzw. daß das Design verworren ist. Das Runtercoden danach 
ist reine Fleißarbeit, das kann auch ein dressierter Affe.

von Wilhelm M. (wimalopaan)


Lesenswert?

Nop schrieb:
> Wilhelm M. schrieb:
>
>> diesem Beispiel heißt das, dass man die Zustandsübergänge abstrakt (ggf.
>> durch eine DESL) beschreibtohne sie im Code zu "verstecken".
>
> In diesem Beispiel ist das Problem doch eher, daß es kein Design zu
> geben scheint, bzw. daß das Design verworren ist. Das Runtercoden danach
> ist reine Fleißarbeit, das kann auch ein dressierter Affe.

Sehe ich auch so. Wenn er kein Diagramm mit Papier und Bleistift malen 
kann, kriegt er es auch nicht in irgendeinen Automaten.

von Nop (Gast)


Lesenswert?

Wilhelm M. schrieb:

> Sehe ich auch so. Wenn er kein Diagramm mit Papier und Bleistift malen
> kann, kriegt er es auch nicht in irgendeinen Automaten.

Jepp, und das setzt sich danach noch fort, weil man ohne so ein Diagramm 
ja auch keine Testfälle entwerfen kann. Und beim reinen Ausprobieren 
werden mit Sicherheit einige Übergänge ausgelassen, besonders die für 
Fehlerbehandlung.

von c-hater (Gast)


Lesenswert?

Wilhelm M. schrieb:

> Ich aber antworte ihm: nimm lieber einen Hammer.

Das glaubst aber auch nur du, vielleicht nichtmal du...

De facto bringen die gegenüber C erweiterten Ausdrucksmöglichkeiten von 
C++ im konkreten Fall natürlich exakt NULL Vorteile.

von Karl (Gast)


Lesenswert?

Christian R. schrieb:
> Hier mal exemplarisch dargestellt.
> Wie kann man das besser lösen?

[ ] in einem Forum Fragen, das vor Freitagstrollen und Besserwissern nur 
so strotzt

[x] Hinsetzen und runterschreiben. Dann schauen ob's so schlimm war und 
DIR gefällt. Oft merkt man auch erst mitten drin, das was am Design 
falsch ist. Natürlich hätte man vorher in einem Forum fragen können, 
aber die Struktur des Programms und die Übergänge hinzutippen dauert 
vielleicht eine Stunde. Das Gesülze im Forum zu lesen dauert einen Tag 
und führt zu nichts.

Und jetzt mein Gesülze, wie ich es gerne mache:
- Welche Zustandsübergänge gibt es?
- Durch welche Signale werden diese ausgelöst?
- Ergibt sich daraus eine vernünftige Schnittstelle?
- Zustandsübergangslogik trennen von den Aktionen in einem Zustand 
(Idealvorstellung der klassischen Digitaltechnik)
- 40 Zustände? So wenige? ;-) Keine Angst, hab Mut

von Possetitjel (Gast)


Lesenswert?

Achim S. schrieb:

> Dass die allermeisten Statemachines von 4*10 auch
> verkleinert werden können (ggf. zum Preis der
> Unleserlichkeit), geschenkt.

Nach meinem Verständnis ging es nicht um Minimierung,
sondern um Allgemeinverständlichkeit.
Das steht, wie Du ja selbst auch sagst, im direkten
Gegensatz zueinander.


> Aber warum das in OOP besser geht als mit Papier
> und Bleistift, UML oder C, ist wohl nur dem klar,
> der OOP besser kann als eines der anderen.

Naja, die Wahrheit ist, dass das "O" in OOP für
"Automaten" steht. Das wissen die OOP-Leute (i.d.R.)
nur nicht.
(Wilhelm bildet die Ausnahmen von dieser Regel.)

Die "Felder", "Membervariablen" etc. bilden die Flipflop-
Batterien der Automaten. Die Routinen ("Methoden") bilden
die Kombinatorik; das Interface entspricht den
Anschlusspins.
Die Schöpfer der OOP sind primär dafür zu hassen, dass
sie unbedingt ein "völlig neues" Pseudo-Universum schaffen
mussten, statt an die seit Ewigkeiten bekannten Begriffe
der Automatentheorie anzuknüpfen.

Mit diesem Vorwissen ist es naheliegend, einen Zusammenhang
zwischen der OOP und den "state machines" zu sehen: "state
machines" sind auch nur (endliche) Automaten.
Zur Laufzeit aufgebaute Hierarchien von "Instanzen" sind
lediglich Automatennetze -- aber das klingt ja nicht so
unverständlich und ist daher uncool...

von Heiko L. (zer0)


Lesenswert?

Man merkt: Die Nichtigkeit einer Abstraktion steigt mit ihrer 
Ausdehnung.
Wenn sie dann schließlich alles umfasst sagt sie absolut gar nichts 
mehr.

von franz0815 (Gast)


Lesenswert?

Lösung in C.


int zustand = 0;  // start
int Automat [4][10], =     {    {3,1,4,6,0,0,0,0,0,0},

                                                                                                            {13,12,12,18,16,12,19,15,11,10},
                                                {3...},
                                                {...}
                            };
zustand = zustand[Automat[zustand][uebergang];

/////////////////
  2 dim Arrays werden im
Speicher hintereinander abgelegt.

von J Zimmermann (Gast)


Lesenswert?

franz0815 schrieb:
> Lösung in C.

warum nicht gleich ein zweidimensionales Feld von Funktionspointern?
mfg

von A. S. (Gast)


Lesenswert?

franz0815 schrieb:
> zustand = zustand[Automat[zustand][uebergang]
Und wofür soll das gut sein?

von MaWin O. (Gast)


Lesenswert?

franz0815 schrieb:
> zustand = zustand[Automat[zustand][uebergang];

syntax error

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
Noch kein Account? Hier anmelden.