Verzwicktes switch-statement



  • horc schrieb:

    Aber es scheint mit ineffizient bei 20 case-Labels.

    Was genau meinst du mit ineffizient? Bezogen auf die Schreibarbeit ist dieses if-else konstrukt imho kürzer aber schlechter wartbar (was in diesem Fall aber imo nicht schlimm ist).
    Ob es so einen switch-Trick gibt, weiss ich nicht (hab ich zum. noch nie gesehen).



  • Hallo,
    wenn der Code in den einzelnen Case-Zweigen unabhängig voneinander ist, kannst du dir auch einfach eine eigene Sprung-Tabelle mit Funktionen bauen:

    void tuwas()
    {
    	cout << "ich tu was" << endl;
    }
    void tuwasanderes()
    {
    	cout << "ich tu was anderes" << endl;
    }
    void tuwasnochanderes()
    {
    	cout << "ich tu noch was anderes" << endl;
    }
    
    void func(int expression, int constant)
    {
    	typedef void (*action)();
    	static action table[3] = {&tuwas, &tuwasanderes, &tuwasnochanderes};
    	int index = ...	// Berechne Index aus expression und constant
    	assert(index < 3);
    	table[ index ]();
    }
    


  • Was wird eigentlich in den case Fällen getestet?

    case constant >> 1:

    Soll der in den case rein, wenn (constant >> 1) ungleich Null ist? Oder welche Fälle gelten hier eigentlich?



  • Ponto schrieb:

    Was wird eigentlich in den case Fällen getestet?

    case constant >> 1:

    Soll der in den case rein, wenn (constant >> 1) ungleich Null ist? Oder welche Fälle gelten hier eigentlich?

    Es sollen hier musikalische Notenwerte ausgegeben werden. Als Referenz wird dazu eine Viertelnote an die Funktion übergeben (in Ticks per Beat). Desweiteren wird die eigentliche Note übergeben (in Ticks per Beat). Die shift-Operationen dienen dem dividieren bzw. multiplizieren. Das soll kein Test sein (ungleich o.ä.)!



  • Es sollen hier musikalische Notenwerte ausgegeben werden. Als Referenz wird dazu eine Viertelnote an die Funktion übergeben (in Ticks per Beat). Desweiteren wird die eigentliche Note übergeben (in Ticks per Beat). Die shift-Operationen dienen dem dividieren bzw. multiplizieren. Das soll kein Test sein (ungleich o.ä.)![/quote]

    Das verwirrt mich mehr als es die Sache aufklärt. Was soll die Funktion genau machen? Was sind die beiden Parameter? und wie würde die Funktion ungefähr mit if aussehen?



  • godlikebot schrieb:

    Was genau meinst du mit ineffizient? Bezogen auf die Schreibarbeit ist dieses if-else konstrukt imho kürzer aber schlechter wartbar (was in diesem Fall aber imo nicht schlimm ist).

    Ich meine, dass der Code ineffizient ist bzgl. Ausführung. Stell dir vor, dass einfach der letzte else-Pfad ausgeführt wird, dann hat der Rechner wesentlich mehr zu tun als bei einem switch. Dort wird lediglich der Ausdruck berechnet und das entsprechende case-label gesucht.



  • ich weiss jetzt nicht, inwiefern das für den noten-kram praktikabel ist, aber könnte man für die konstante nicht auch ein enum nehmen?



  • Könnte es so auch funktionieren?

    int max_labels = 20;
    
    for (i=1; i<=max_labels; i++)
    {
        if ((constant >> i) == expression)
        {
            // tu halt was dagegen :)
            break;
        }
    }
    


  • Ponto schrieb:

    Das verwirrt mich mehr als es die Sache aufklärt. Was soll die Funktion genau machen? Was sind die beiden Parameter? und wie würde die Funktion ungefähr mit if aussehen?

    Kleines Beispiel:

    1. Parameter: Viertelnote als Referenz
    2. Parameter: eine beliebige Note

    Viertelnote habe: 384 Ticks
    beliebige Note habe: 192 Ticks

    Ich schreib jetzt mal modifizierten Code:

    switch(192)
    {
      case 384 >> 3: 32tel-Note;         // 384 >> 3 = 48
      case 384 >> 2: 16tel-Note;         // 384 >> 2 = 96; 
      case 384 >> 1: 8tel-Note;          // 384 >> 1 = 192; 
      ...
    }
    

    Das Problem der switch-Anweisung: Die Viertelnote muss nicht 384 Ticks haben, es können auch andere Werte vorkommen; daher wird dies als Parameter übergeben. Ansonsten könnte ich die 384 ja "fest verdrahten".

    Gruß,
    Göbel



  • Sag das doch direkt.

    void func(int ref, int val)
    {
       switch ( (val * 8)/ ref) {
          case 1:  std::cout << "1/32" << std::endl; break;
          case 2:  std::cout << "1/16" << std::endl; break;
          case 4:  std::cout << "1/8" << std::endl; break;
          case 8:  std::cout << "1/4" << std::endl; break;
          case 16:  std::cout << "1/2" << std::endl; break;
          case 32:  std::cout << "1/1" << std::endl; break;
          default:  std::cout << "unbekannt" << std::endl;
       }
    }
    


  • Ponto schrieb:

    void func(int ref, int val)
    {
       switch ( (val * 8)/ ref) {
          case 1:  std::cout << "1/32" << std::endl; break;
          case 2:  std::cout << "1/16" << std::endl; break;
          case 4:  std::cout << "1/8" << std::endl; break;
          case 8:  std::cout << "1/4" << std::endl; break;
          case 16:  std::cout << "1/2" << std::endl; break;
          case 32:  std::cout << "1/1" << std::endl; break;
          default:  std::cout << "unbekannt" << std::endl;
       }
    }
    

    @Ponto: Klasse Idee, besten Dank!!

    Gruß,
    Göbel


Anmelden zum Antworten