Forum: Compiler & IDEs switch auf struct


von Christian B. (chrblank)


Lesenswert?

Moin Leute,

der Zeit schreibe ich an einem Programm, das in der Grundstruktur ein 
endlicher Automat mit 8 Zuständen ist. Die Zustände werden durch 3 
Faktoren beschrieben: Editiermodus (Ja/Nein), Optionsmenü aktiv 
(Ja/Nein), Cursorposition (0,1,2). Diese habe ich wie folgt definiert:

enum editierbar {NO_EDIT=0, EDIT};
enum optdialog {NO_OPTION=0, OPTION};
enum postion {POS1=0, POS2, POS3};

Diese Faktoren haben ich in einem struct zusammengefasst.

typedef  struct
{
  enum editierbar edit;
  enum optdialog opt;
  enum postion pos;
}status;

Diese Definitionen stehen in der Header-Datei.
Im Main deklariere und initialisiere ich die Variable "zustand":

status zustand={NO_EDIT,NO_OPTION,POS1};

Mein Ziel ist es, das ich ein Switch nutze wie folgt:

switch (zustand.edit|zustand.opt|zustand.pos)
{
case NO_EDIT|NO_OPTION|POS1:
usw...

leider funktioniert dies nicht wie gewünscht. Der Compiler berichtet, 
dass die folgenden Cases schon definiert wurden. Bisher habe ich im Web 
keine Ansätze für eine ähnliche Umsetzung in C gefunden. Kann C (WinAVR) 
eine solche Lösung abbilden?

Vielen Dank für eure Hilfe!
Gruß,
Christian.

von (prx) A. K. (prx)


Lesenswert?

#define X(e,o,p) ((e)<<4|(o)<<2|(p))

switch (X(zustand.edit,zustand.opt,zustand.pos)) {
case X(NO_EDIT|NO_OPTION|POS1):
...

von Andreas R. (rebirama)


Lesenswert?

Hi!

der ausdruck "NO_EDIT|NO_OPTION|POS1" ist ein binäres oder aus den 3 
enums, und hat damit den wert 1 egal ob es nun EDIT oder NO_EDIT heißt.
Folglich bekommst du doppelte Cases :-)

eine lösung wäre:

temp= status.edit + status.opt<<1 + status.pos<<2;

switch (temp)
{
case (NO_EDIT + NO_OPTION<<1 + POS1<<2):
...

}

Alternativ:
kannst du die shifterei gleich in die Enums ziehen:
enum editierbar {NO_EDIT=0, EDIT=1};
enum optdialog {NO_OPTION=0, OPTION=2};
enum postion {POS1=0, POS2=4, POS3=8};

und sonst bei deinem code bleiben.

von (prx) A. K. (prx)


Lesenswert?

Andreas R. wrote:

> temp= status.edit + status.opt<<1 + status.pos<<2;

Guck dir das Kapitel über die Operator-Prioriäten lieber noch mal an. 
Mit "|" funktioniert das so, mit "+" nicht.

von Christian B. (chrblank)


Lesenswert?

A. K. wrote:
> #define X(e,o,p) ((e)<<4|(o)<<2|(p))
>
> switch (X(zustand.edit,zustand.opt,zustand.pos)) {
> case X(NO_EDIT|NO_OPTION|POS1):
> ...

Moin!

Vielen Dank für eure schnellen Antworten. Ich habe die oben zitierte 
Implementierung umgesetzt und meinen Code um diesen erweitert. Hat super 
geklappt, mit der Modifikation, nur musste ich statt

case X(NO_EDIT|NO_OPTION|POS1):

das schreiben:

case X(NO_EDIT,NO_OPTION,POS1):

Läuft super rund. Ich probiere den Ansatz noch mal etwas zu beschreiben, 
wie ich ihn verstanden habe, damit die Lösung ggf. auch von anderen 
leichter zu finden ist.

Durch das "#define X(e,o,p) ((e)<<4|(o)<<2|(p))" wird X mit 3 Parametern 
definiert, die je nach Stelle um 4 bzw. 2 Bit nach Links verschoben 
werden, so das man in X, alle 3 Faktoren kodiert in einem Wert. Auf 
diesen nun einen Wert kann man leicht ein Switch laufen lassen.

Vielen Dank noch mal!

Gruß,
Christian

von (prx) A. K. (prx)


Lesenswert?

Christian Blank wrote:

> case X(NO_EDIT|NO_OPTION|POS1):
> das schreiben:
> case X(NO_EDIT,NO_OPTION,POS1):

Yep, sorry. Cut-and-paste Fehler.

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.