www.mikrocontroller.net

Forum: Compiler & IDEs switch auf struct


Autor: Christian Blank (chrblank)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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):
...

Autor: Andreas R. (rebirama)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian Blank (chrblank)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.