Verschachtelte IFs ohne Redundanz möglich?

Gast #6045659
Eigentlich ein allgemeines Programmierproblem. Habe gerade folgenden 
Code:
1
If analog_richtung Then
2
  If analog_pwm Then
3
    Low IN1
4
  Else
5
    High IN1
6
  Endif
7
Else
8
  If analog_pwm Then
9
    Low IN2
10
  Else
11
    High IN2
12
  Endif
13
Endif

Wie man sieht, unterscheiden sich die beiden Zweige minimal. Kann man 
das verschönern und die Redundanz rausnehmen? Da es sich hier um 
konkreten Mikrocontroller-Code (Oshonsoft Basic für PIC16) handelt wäre 
noch die Frage, was für eine Variante kleiner, schneller oder schöner 
ist.

Hier soll er schnell sein, weil in der INT.

Dieses Beispiel ist jetzt einfach, vielleicht zu einfach um es zu 
vereinfachen, zeigt aber die Problematik auf. Ich hatte schon 
(Windows-)Programme geschrieben, die hatten riesen Redundanz im Code 
wegen paar Kleinigkeiten.

Man kann das Problem sogar noch erweitern auf z.B. Datenblätter. Die 
habe ich einmal in einem Ordner mit allen DBs, aber auch im Ordner eines 
Projekts. OK, beim heutigen Speicherplatz kein Problem, ist aber nicht 
schön. Und Photos, wo mache ich die rein? In den Projektordner oder zu 
den Photos? Sind Hardlinks die Lösung?

Gruss Chregu
Gast #6045662
Switch Case, wenn Du die 2 unabhängigen binären zustande zu einem 
zusammenfassen kannst.

Ansonsten je nach Komplexität der Körper auch Funktionen, Datenarrays 
etc.
Gast #6045665
Die ist doch nur code-redundanz, aber in jedem Ausführungspfad sind 
genau nur so viele IFs wie nötig. Egal, wie irgendein IF ausgeht, es 
sind zum Schluss nur 2 Sprünge die gemacht werden. Die Schönheit des 
Codes hat hier nichts mit der Geschwindigkeit zu tun.
Gast #6045668
If analog_richtung Then
 pin = IN1
Else
 pin = IN2
Endif


If analog_pwm
 Low pin
Else
 High pin
Endif


Finde ich gut lesbar. Ich persönlich würde pin wahrscheinlich immer 
vorhalten und nur umschalten wenn von ein Richtungswechsel passiert.
Gast #6046329
Peter D. schrieb:
> Eleganter ist es, beide Bedingungen EXOR zu verknüpfen. Das erspart dann
> das 2-malige Hinschreiben und Lesen.
> Schneller ist es aber nicht.

Der TO hat ja genau keine Redundanz: Er hat 2 "Pins" (IN1, IN2) und je 2 
Zustände. Also genau 4 Aktionen, getriggert durch 2*2 Eingangszustände.
Gast #6046577
A. S. schrieb:
> Der TO hat ja genau keine Redundanz

Ja hast schon Recht. Sehen wir es so an: In der zweiten Ebene sind beide 
Male die genau gleichen Abfragen, sie wären austauschbar mit den 
Aeusseren. Es ist zweidimensional! Eine Tabelle.
1
+---------+--------------+--------------+
2
¦         ¦ richtung = 1 ¦ richtung = 0 ¦
3
+---------+--------------+--------------+
4
¦ pwm = 1 ¦ Low IN1      ¦ High IN1     ¦
5
+---------+--------------+--------------+
6
¦ pwm = 0 ¦ Low IN2      ¦ High IN2     ¦
7
+---------+--------------+--------------+

Man könnte auch die Y-Achse als äussere Abfrage nehmen. Die Tabelle kann 
viel grösser sein, oder sogar mehr als zwei Dimensionen haben. Ich meine 
nur dass sich die inneren Abfragen immer wiederholen!

Gruss Chregu
#6046582
A. S. schrieb:
> Der TO hat ja genau keine Redundanz:

Stimmt, es sind 4 Fälle.
Damit man nicht eine Bedingung mehrfach hinschreiben muß, kann man beide 
in eine Variable kombinieren und per switch/case auswerten.
In C würde das so aussehen:
1
  uint8_t i = !!analog_richtung;
2
  if (analog_pwm)
3
    i |= 2;
4
  switch (i){
5
    case 0: High_IN2(); break;
6
    case 1: High_IN1(); break;
7
    case 2: Low_IN2(); break;
8
    case 3: Low_IN1(); break;
9
  }
Gast #6046640
Die Eingangsgrößen als bits in einem Decoder-Wort zu sehen ist doch gar 
nicht so schlecht als Idee.
Lesbarer finde ich (zumindest bei den zwei Werten) aber immer noch 
meinen obigen Vorschlag.

1
uint8_t decode = analog_richtung + 2*analog_pwm; //ggf. + 4* analog_gimmick; 
2

3
  switch (i){
4
    case 0: High_IN2(); break;
5
    case 1: High_IN1(); break;
6
    case 2: Low_IN2(); break;
7
    case 3: Low_IN1(); break;
8
    //(...)
9
  }

Muss nur sichergestellt werden, dass decode korrekt zusammengebaut wird, 
also der Wertebereich der Eingangsgrößen immer 0/1 ist. (Oder halt 
anders schieben)
Und man kann die Logiktabelle noch in den Code kommentieren.
Gast #6046693
Zoidberg schrieb:
> switch (i){

Du meinst
1
switch (decode){

Oder ich fände noch praktisch:
1
uint8_t decode = analog_richtung + %00000010*analog_pwm; //ggf. + %00000100* analog_gimmick; 
2

3
  switch (decode){
4
    case %00000000: High_IN2(); break;
5
    case %00000001: High_IN1(); break;
6
    case %00000010: Low_IN2(); break;
7
    case %00000011: Low_IN1(); break;
8
    //(...)
9
  }

Gruss Chregu
#6046781
Zoidberg schrieb:
> uint8_t decode = analog_richtung + 2*analog_pwm; //ggf. + 4*
> analog_gimmick;
>
>   switch (i){
>     case 0: High_IN2(); break;
>     case 1: High_IN1(); break;
>     case 2: Low_IN2(); break;
>     case 3: Low_IN1(); break;
>     //(...)
>   }

Dann vielleicht sogar
1
#define DIR_HI  0x00
2
#define DIR_LO  0x02
3
#define PWM_2   0x00
4
#define PWM_1   0x01
5

6
switch(analog_richtung | (analog_pwm << 1)) {
7
  case DIR_HI | PWM_2: High_IN2(); break;
8
  case DIR_HI | PWM_1: High_IN1(); break;
9
  case DIR_LO | PWM_2: Low_IN2(); break;
10
  case DIR_LO | PWM_1: Low_IN1(); break;
11
}

EDITH sagt: aber am besten mag ich immer noch den Origonal-Code vom TO!
#6046929
Christian M. schrieb:
> Wie man sieht, unterscheiden sich die beiden Zweige minimal. Kann man
> das verschönern und die Redundanz rausnehmen?

Immer wenn man strukturell identischen Code hat (Redundanz), ist das ein 
Indiz, dass man diese Redundanz durch generischen Code herausnehmen 
kann.

In einer Sprache, die das generische Paradigma unterstützt, wie etwa 
C++, könnte man folgendes formulieren:
1
#include <iostream>
2
#include <type_traits>
3

4
// das folgende wäre im echten Leben eine Pin-Klasse, die eh schon da ist.
5
template<bool B> using ActiveHigh = std::integral_constant<bool, B>;
6

7
template<typename ActiveHigh> 
8
struct In {
9
    inline static void activate(bool b) {
10
        if (b ^ ActiveHigh::value) {
11
            // whatever todo for high()            
12
        }    
13
        else {
14
            // whatever todo for low()
15
        }
16
    }
17
};
18

19
// der tatsächlich benötigte Code
20

21
using In1 = In<ActiveHigh<true>>;
22
using In2 = In<ActiveHigh<false>>;
23

24
int main() {
25
    bool analogRichtung{};
26
    bool analogPwm{};
27
 
28
    if (analogRichtung) {
29
        In1::activate(analogPwm);
30
    }
31
    else {
32
        In2::activate(analogPwm);
33
    }
34
}
Gast #6046992
>dafür ist ja die doppelte negierung da


Ja, schon klar, allerdings hat der Poster einen Basic Dialekt und MaWin 
regte eine offensichtlichere Schreibweise an.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.