C nested Schalter: Außenschalter der Fall innerhalb des inneren Schalters

stimmen
1

Ich füge Koroutine Unterstützung eines Dolmetschers Ich schreibe und ich möchte so etwas wie die folgenden Funktionen ausführen:

typedef enum {
    bar_stuff,
    bar_other
    } Bar;

typedef enum {
    foo_error=-1,
    foo_none=0,
    foo_again
    } Foo_state;

Foo_state do_foo(Bar bar,Foo_state foo)
    {
    switch(foo)
        {
        case foo_none: //start
        switch(bar)
            {
            case bar_stuff:
                //do stuff
                return foo_none;
            case bar_other:
                //do other stuff
                return foo_again;
                case foo_again: //!! this doesn't work
                    /* edit: this is supposed to be a case of
                     *     switch(foo), not switch(bar)
                     */
                //do more other stuff
                return foo_none;
            default:
                //stuff
                return foo_none;
            }
        default:
            //fail
            return foo_error;
        }
    }

Offensichtlich dosn't diese Arbeit (ich doppelten Fallwert, Alternative ist wahrscheinlich nicht definiertes Verhalten / segfault). Ich könnte Schalter (bar) als eine if / else if / else-Kette schreiben, aber ich hatte gehofft, es war eine bessere Art und Weise.

Ich bin mit gcc, ob das einen Unterschied macht.

Bearbeiten:

Die folgende funktionieren würde, aber wäre ein PITA zu halten sein:

Foo_state do_foo2(Bar bar,Foo_state foo)
    {
    switch(foo)
        {
        case foo_none:  goto case_foo_none;
        case foo_again: goto case_foo_again;
        default:
            //fail
            return foo_error;
        }
    case_foo_none: //start
    switch(bar)
        {
        case bar_stuff:
            //do stuff
            return foo_none;
        case bar_other:
            //do other stuff
            return foo_again;
            case_foo_again:
            //do more other stuff
            return foo_none;
        default:
            //stuff
            return foo_none;
        }
    }

Edit 2:

Nun, dies scheint nicht zu dem oben genannten ‚besseren Weg‘ zu nachgiebig, so würde Ich mag wissen, ob jemand ein Problem sieht damit wie folgt zu schreiben:

Foo_state do_foo3(Bar bar,Foo_state foo)
    {
    switch(foo)
        {
        case foo_none: //start
        if(bar == bar_stuff)
            {
            printf(do stuff\n);
            return foo_none;
            }
        else if(bar == bar_other)
            {
            printf(do other stuff\n);
            return foo_again;
            case foo_again: //continue
            printf(do more other stuff\n);
            return foo_none;
            }
        else
            {
            printf(stuff\n);
            return foo_none;
            }
        default:
            //fail
            return foo_error;
        }
    }

Das Problem, das ich mit diesem zu sehen ist ein bar_ * -Wert fehlt (da gibt es mehrere Funktionen wie diese, und einige der Aufzählungen haben Dutzende von Werten), aber ich nehme an, ein Testskript für das funktionieren sollte ...

Veröffentlicht am 30/12/2009 um 04:05
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
4

Hm ... ein Äquivalent eines Karnaugh Karte verwenden, um die Logik zu vereinfachen und das alles mit

if (cond1 && cond2) {
  doX();
  return;
}
if (cond3 && cond4) {
  doY();
  return;
}
// Sometimes you can take shortcuts
if (cond5) {
   doZ();
} else {
   doW();
}
return;

Dieser Code ist lesbar. Verschachtelte Dinge am besten vermieden werden, wenn möglich.

zuerst die einfachsten Bedingungen Überprüfung wird die Funktion einfacher.

In Ihrem Fall START MIT:

Foo_state do_foo2(Bar bar,Foo_state foo) {
  if (foo != foo_none && foo != foo_again) {
    return foo_error;
  }
  ...

  if (foo == foo_none) {
    ...
  }
  // Implicit Else
  ...
Beantwortet am 30/12/2009 um 04:10
quelle vom benutzer

stimmen
1

Eine einfache Lösung wäre es, die Werte in der bar_ Enum zu ändern, so dass sie in Bezug auf die foo_ Enum einzigartig sind. Das bezieht sich nicht auf die Tatsache jedoch, dass der Code verwirrend ist. Warum sollte man sich für einen foo_ Wert innerhalb der bar_ switch-Anweisung? Syntaktisch, es gilt (solange die Werte eindeutig sind), aber seine schlechte Codierung.

Beantwortet am 30/12/2009 um 04:16
quelle vom benutzer

stimmen
6

Sie können auch gerade auf {} in jedem Fall: Aussage ,
ohne sie der ganze Fall Stapel als eine Einheit bewertet wird, so können keine Variablen in einem Fall festgelegt werden:

Aber indem sie

 case blah:
 {
  // do stuff
 }
 break;

Sie können innerhalb der Case-Anweisung anythign Sie setzen.

Beantwortet am 30/12/2009 um 04:31
quelle vom benutzer

stimmen
0

Ok, es scheint, dass Ihr Code tut dies:

bar \ foo   foo_none                          foo_again                             other
bar_stuff   doStuff, return foo_none          do more other stuff, return foo_none  return foo_error
bar_other   do other stuff, return foo_again  do more other stuff, return foo_none  return foo_error
other       stuff, return foo_none            do more other stuff, return foo_none  return foo_error

Dies ist, was ich von einer Karnaugh Karte gemeint. Nun, hier ist die einfachste Umsetzung:

Foo_state do_foo2(Bar bar,Foo_state foo) {
  if (foo == foo_again) {
    // do more stuff
    return foo_none;
  }
  if (foo != foo_none) { // other
    return foo_error;
  }
  // foo_none
  if (bar == bar_stuff) {
    // do stuff
    return foo_none;
  }
  if (bar == bar_other) {
    // do other stuff
    return foo_again;
  }
  // At this point bar = other

  // stuff
  return foo_none;
}

Ich glaube, das das gleiche wie Ihr Code tut, aber nicht Schalter und gotos verwenden. Sie können eine Tabelle mit dem Ergebnis, ausfüllen, und Sie können auch beiden Implementierungen durch einen Unit-Tests setzen, um sicherzustellen, dass sie die gleiche Sache für alle Eingänge zu tun.

Beantwortet am 30/12/2009 um 15:26
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more