Mehrfache if.Verkleinern

Gast #5976506
Lesenswert?

Hallo meine Frage frage.

Habe 200 Led´s und wollte nicht 200 mal eine if abfrage machen.

Kann ich sowas auch verkleiner oder zusammenfügen?

Zb
1
if (incoming == "ledaus") 
2
    {
3
      leds[0] = CRGB::Black;
4
      FastLED.show();
5
      Serial.println("Led´s ausgeschaltet"); 
6
      }
7
      if (incoming == "start") 
8
      {
9
      leds[0] = CRGB::Green;
10
      FastLED.show();
11
      Serial.println("you started the demo routine"); 
12
      }
13
      if (incoming == "ledaus") 
14
      {
15
      leds[1] = CRGB::Black;
16
      FastLED.show();
17
      Serial.println("Led´s ausgeschaltet"); 
18
      }
19
      if (incoming == "1") 
20
      {
21
      leds[1] = CRGB::Red;
22
      FastLED.show();
23
      Serial.println("you started the demo routine");
24
      }
25
      if (incoming == "ledaus") 
26
      {
27
      leds[2] = CRGB::Black;
28
      FastLED.show();
29
      Serial.println("Led´s ausgeschaltet");
30
      }
31
      if (incoming == "2") 
32
      {
33
      leds[2] = CRGB::Red;
34
      FastLED.show();
35
      Serial.println("you started the demo routine");
36
      }
37
      if (incoming == "ledaus") 
38
      {
39
      leds[3] = CRGB::Black;
40
      FastLED.show();
41
      Serial.println("Led´s ausgeschaltet");
42
      }
43
      if (incoming == "3") 
44
      {
45
      leds[3] = CRGB::Red;
46
      FastLED.show();
47
      Serial.println("you started the demo routine");
48
      }
Danke für die super klotage und mein Hirn
#5976515
Lesenswert?

Abhängig von der Sprache und Laufzeitbedingungen könntest Du zum 
Beispiel ein Array von Structs machen welche jeweils 3 Elemente haben. 
Das erste ist Dein "incoming"-Wert, das zweite der Wert für leds[3], der 
dritte Dein Debugtext.

Du schreibst dann daraum eine Schleife die alle 200 Einträge dieser 
Liste durchgeht und dann beim richtigen die entsprechende Aktion mach 
und dann raus springt.

Wenn Incoming auch nur eine Zahl sein darf, dann kannst Du das nach 
einer Bereichtsüberprüfung direkt als Index in die Tabelle verwenden. 
Alternativ kannst Du auch mit Vergleichen und einer sortierten Liste 
arbeiten, dann reduzierst Du die Durchläufe von n auf log(n)... was aber 
bei 200 Einträgen noch nicht so viel ausmacht.

Es ist aber gut, dass Du siehst, dass solche Strukturen unschön sind. 
Ein gängiger Weg solche Probleme zu lösen ist über eine Datenstruktur zu 
gehen.
Gast #5976526
Lesenswert?

Sieht nach C++ aus.

In Java und C# könntest du diese if-Kette durch switch-case ersetzen. 
leider geht das in C++ nicht.

Du könntest allerdings das Schlüsselword else benutzen, um die 
Ausführung nach einem Treffer abzukürzen. Leider sieht das aber nicht 
schöner aus, als der jetzige Quelltext.

Ehrlich gesagt finde ich das auch nicht schlimm. Es ist klar erkennbar, 
was der Code tun soll. Das wichtigste Kriterium für guten Quelltext ist 
daher schon erfüllt.

An der Einrückung würde noch arbeiten.
#5976535
Lesenswert?

Sepplhuber schrieb:
> if (incoming == "ledaus")

Schön, wenn man Code aus dem Zusamenhang reißt und dann der Leser 
rumrätseln darf.
Wie ist denn incoming definiert?

Wenn man freundlich ist, dann postet man Codeschnipsel immer so, daß sie 
auch compilieren, d.h. mit allen nötigen Deklarationen.

Sepplhuber schrieb:
> Habe 200 Led´s und wollte nicht 200 mal eine if abfrage machen.

Dann beschreibe einfach mal, was Du überhaupt machen willst.
#5976540
Lesenswert?

Sepplhuber schrieb:
> Genau da liegt mein problem es sollen mal über 1000Leds damit gesteuert
> werden. dann müsste ich alles 1000 mal schreiben %rolleyes%

das schreit doch geradezu nach einer Schleife:
sieht nach c# oder Arduino aus das deutet darauf hin:
      FastLED.show();
      Serial.println("Led´s ausgeschaltet");
1
for(uint16_t i = 0; i<1000; i++)
2
{ 
3
   if(!strcmp(incoming, "ledaus"))
4
   {
5
      leds[i] = CRGB::Black;
6
      FastLED.show();
7
   }
8
   // alternativ FastLED.show(); am ENDE der Schleife
9
}

man sollte aber incoming noch erweitern WELCHE LED an oder aus sein 
soll, also das Kommando noch zerlegen.
Gast #5976541
Lesenswert?

Bin bei einem Pick to Light System funktioniert alles Super , Programm 
wurde um den Arduino Uno anzusteuern mit C# geschrieben.

[c]

String incoming = "";
void loop(){

 if (Serial.available())
  {
    incoming = Serial.readStringUntil('\n');
    Serial.println(incoming);
    {
    if (incoming == "ledaus")
    {
      leds[0] = CRGB::Black;
      FastLED.show();
      Serial.println("Led´s ausgeschaltet");
      }
      if (incoming == "start")
      {
      leds[0] = CRGB::Green;
      FastLED.show();
      Serial.println("you started the demo routine");
#5976542
Lesenswert?

Sepplhuber schrieb:
> Hallo meine Frage frage.
>
> Habe 200 Led´s

Und einen Deppenapostroph.

>und wollte nicht 200 mal eine if abfrage machen.

Wer will das schon?

> Kann ich sowas auch verkleiner oder zusammenfügen?

Sicher.

>
> Zb
>
> <c/>

Formatierungen brauchen hier eckige Klammern [ ]

> Danke für die super klotage und mein Hirn

Wie sieht denn deine Kommandostruktur aus?
Logischerweise muss man das Kommando dekodieren und daraus einen Index 
einer Variable berechnen und eben NICHT 200 Vergleiche machen. Außerdem 
erscheint mir deine Steuerlogik mehr als fragwürdig.

Die Formatierung deines Quelltextes ist sehr schlecht, man sieht die 
Struktur nicht!
(Firma: Schweigstill IT) Persönliche Seite #5976550
Lesenswert?

Wenn es sich um ein Programm in C handeln sollte, lässt es sich wie 
folgt vereinfachen:
1
{}

incoming wird nämlich sicherlich nicht die Adresse der nur lokal 
gültigen Stringliterals "ledaus", "start", usw. beinhalten, so dass der 
Vergleich in jedem Fall scheitern wird. Ob der Compiler dies auch selbst 
erkennen kann, hängt von der Vorgeschichte von incoming ab. Falls er 
dazu in der Lage sein sollte, wird der Compiler ein sehr aussagekräftige 
Warnung ausgeben.
#5976553
Lesenswert?

So als Ansatz
1
if (incoming == "ledaus") {
2
  leds[lednr] = CRGB::Black;
3
  FastLED.show();
4
  Serial.println("Led´s ausgeschaltet");
5
}
6

7
if (incoming == "start") {
8
  leds[lednr] = CRGB::Green;
9
  FastLED.show();
10
  Serial.println("you started the demo routine");
11
}
12

13
int tmp = atoi(incomming);
14
if (tmp >0 && tmp<200 ) {
15
  lednr = tmp;
16
  Serial.println("you started the demo routine");
17
}
(Firma: egal) #5976569
Lesenswert?

Joachim B. schrieb:
> Serial.println("Led´s ausgeschaltet");
> for(uint16_t i = 0; i<1000; i++)
> {
>    if(!strcmp(incoming, "ledaus"))
>    {
>       leds[i] = CRGB::Black;
>       FastLED.show();
>    }
>    // alternativ FastLED.show(); am ENDE der Schleife
> }

Wohl eher sorum:
1
if(!strcmp(incoming, "ledaus"))
2
{
3
  for(uint16_t i = 0; i<1000; i++)
4
  {
5
    leds[i] = CRGB::Black;
6
  }
7
  FastLED.show();
8
  Serial.println("Led´s ausgeschaltet");
9
}

1000 ma die selbe if macht nicht wirklich Sinn und die print würde bei 
dir immer aufgerufen auch wenn der Befahl garnicht "ledaus" lautet.
#5976620
Lesenswert?

Falk B. schrieb:
> Und einen Deppenapostroph.

Falk B. schrieb:
> So als Ansatz
> if (incoming == "ledaus") {
>   leds[lednr] = CRGB::Black;
>   FastLED.show();
>   Serial.println("Led´s ausgeschaltet");
> }

hattest du doch gerade moniert?

Irgend W. schrieb:
> Wohl eher sorum:

hast Recht war ja nur grob fertig, klar kommt erst mal:

1. Befehl (was zu tun)
2. wer (bitteschön -> was wie wo -> welche LED eine Spezielle oder 
alle?)

je nach Geschmacksrichtung und Belieben ausbaufähig.
#5976632
Lesenswert?

Sepplhuber schrieb:
> if (incoming == "ledaus")
>     {
>       leds[0] = CRGB::Black;
>       FastLED.show();
>       Serial.println("Led´s ausgeschaltet");
>       }
>       if (incoming == "start")

Warum sollte sich plötzlich incoming auf magische Weise geändert haben?
Zwischen den beiden ifs ist kein Schreibzugriff auf incoming.
Da steht immer noch "ledaus", d.h. der Vergleich mit "start" ergibt 
immer false.

Typischer Weise parst man eine komplette Zeile, d.h. zerlegt sie in 
Befehl, Argument 1, Argument 2 usw. Sind Argumente Zahlen, weist man sie 
einer Variablen zu, z.B. LED-Nummer, LED-Farbe usw).
Hier mal ein Beispiel in C:
1
void execute(char* buf)
2
{
3
  if (*buf == '\0')                                     // do nothing on empty commands
4
    return;
5
  cmd_data.answer = buf;                                // answer overwrite command
6
  cmd_data.cmd_tok = strtok(buf, " ");                  // command token
7
  cmd_data.par_tok = strtok(NULL, " ");                 // parameter token
8
  cmd_data.val_tok = strtok(NULL, " ");                 // value token
9
  for (command_t* cmd_p = cmd_table; pgm_read_byte(cmd_p->cmd) != '\0'; cmd_p++)
10
  {
11
    if (cmd_strcmp_P(cmd_data.cmd_tok, cmd_p->cmd) == 0)
12
    {
13
      func f_ptr = (func)pgm_read_word(&cmd_p->func);
14
      f_ptr();
15
      return;
16
    }
17
  }
18
  answer_err(CMDERR_UNKNOWN_CMD);
19
}
Die Befehle mit Funktionspointer stehen in einem Array.
Gast #5976636
Lesenswert?

Sepplhuber schrieb:
> Vielen Dank allen hat super Funktioniert, mein Arduino ist gerade
> abgeraucht.

so richtig mit "magischer Rauch kommt raus" oder einfach nur "er tut 
nicht was ich gerne hätte"?
den magischen Rauch frei zu lassen muss man mit einer Programmänderung 
auch mal schaffen.
Persönliche Seite #5976650
Lesenswert?

Bischen rumgespielt, hoffentlich hab ich alles richtig gelesen. Da jeder 
if block gleich wieder geschlossen wird, kann man da einiges verkürzen. 
Und wenn eh C++ verwendet wird ...
1
#include <map>
2
#include <string>
3
using namespace std;
4

5
enum func_e {
6
  LED_OFF   = 0,
7
  LED_START,
8
  LED_1,
9
  LED_2,
10
  LED_3,
11
};
12

13
enum color_e {
14
  Black,
15
  Red,
16
  Green,
17
};
18

19

20
map<string, func_e> funcs = {
21
  { "ledaus", LED_OFF   },
22
  { "start" , LED_START },
23
  { "1"     , LED_1     },
24
  { "2"     , LED_2     },
25
  { "3"     , LED_3     },
26
};
27

28

29
int leds[4] = { 0 };
30

31
void show()
32
{
33
}
34

35
void LedFunc(const string& incoming)
36
{
37
  auto it = funcs.find(incoming);
38
  if(it == funcs.end())
39
    return;
40

41
  func_e func = it->second;
42
  
43
  switch(func) {
44
    case LED_OFF:
45
      leds[0] = Black;
46
      leds[1] = Black;
47
      leds[2] = Black;
48
      leds[3] = Black;
49
      break;
50
    case LED_START:
51
      leds[0] = Green;
52
      break;
53
    default: {
54
      int idx = (func - LED_1) +1;
55
      if(idx > 3)
56
        return;
57
      leds[idx] = Red;
58
    } break;
59
  }
60

61
  show();
62

63
  if(!func)
64
    printf("Leds ausgeschaltet");
65
  else
66
    printf("you started the demo routine");
67
}
Gast #5976686
Lesenswert?

Der ganze code ist so wirr, da sollte man damit anfangen sich zu 
überlegen, was man überhaupt will.
Und dann noch alles per String übergeben. Oder Strings dazu verwenden 
...

... da wäre es schon eine geeignete Strafarbeit alle 800 Möglichkeiten 
einzeln per if und string hinzuschreiben.

Think!
#5976727
Lesenswert?

Dirk B. schrieb:
> strtok ist doof, da nicht reentrant.

Wozu sollte jemand sowas brauchen?
Sepplhuber wird bestimmt kein Multitasking auf seinem Arduino Uno laufen 
haben und damit auch keine 2 UARTs gleichzeitig parsen wollen.
Und selbst wenn, dann kann man einfach die 3 Zeilen atomar kapseln.
Man muß nicht Probleme an die Wand malen, wo keine sind.

Dirk B. schrieb:
> sscanf kann man da auch einsetzen.

Dann muß man wieder entsprechend lange Puffer reservieren, was auch 
fehleranfällig sein kann.
Und der Formatstring bei scanf ist auch eine Wissenschaft für sich. Was 
passiert bei "%5s %5s", wenn der erste String 6 Zeichen lang ist?
Muß man nicht gelesene Strings vorher nullen?
Persönliche Seite #5977496
Lesenswert?

Schau dir mal den Ansatz von mir an, ggf. kommst damit weiter.
Vielleicht solltest du aber nochmal einen Schritt zurücktreten, und dir 
die Anforderungen einmal neu anschauen - schreib doch mal hier auf, was 
überhaupt erreicht werden soll.
Deine "200 LEDs" musst du auf jeden Fall rechnerisch ansteuern, nicht 
mit 200 ifs.

Siehe dazu mein Beispiel (aus deinem Code umgebaut):
1
int idx = (func - LED_1) +1;
2
if(idx > 3)
3
  return;
4
leds[idx] = Red;
#5977583
Lesenswert?

Peter D. schrieb:
> Dirk B. schrieb:
>> strtok ist doof, da nicht reentrant.
>
> Wozu sollte jemand sowas brauchen?

Z.B. wenn du einen (Sub-)String scannen möchtest.

Peter D. schrieb:
> Und der Formatstring bei scanf ist auch eine Wissenschaft für sich. Was
> passiert bei "%5s %5s", wenn der erste String 6 Zeichen lang ist?

Es werden nur 5 Zeichen gelesen.

> Muß man nicht gelesene Strings vorher nullen?

Nein.
Das macht sscanf, wenn gültige Zeichen gefunden worden - andernfalls 
wird garnichts geschrieben.
Gast #5977590
Lesenswert?

Sepplhuber schrieb:
> if (incoming == "ledaus")

Ist ein direkter "==" bei einem String möglich?
"ledaus" ist ein Zeiger auf das erste Zeichen - in diesem Fall "l".

incoming ist zwar auch ein Zeiger, aber sicherlich nie auf genau dieses 
"ledaus".

Das geht zwar in einigen Skriptsprachen, aber nicht in C/C++.
Gast #5977599
Lesenswert?

Bei solcher Menge an Möglichkeiten wäre ein binärere Baumstruktur auch 
cool.

1. Buchstabe checken, links oder rechts weiter
2. Buchstabe checken: links oder rechts weiter
3. Buchstabe checken: links oder rechts weiter
4. Buchstabe checken: links oder rechts weiter
5. ....
6. ...
7. ..
....

RatzFatz ist man bei dem richtigen Eintrag, jedesmal egal was empfangen 
wurde.
(Firma: Schweigstill IT) Persönliche Seite #5977621
Lesenswert?

Brummbär schrieb:
> "ledaus" ist ein Zeiger auf das erste Zeichen - in diesem Fall "l".

Nein, das ist nicht korrekt! Man kann lediglich sagen, dass sich ein als 
Stringliteral verwendetes character-Array bei Vergleichen wie ein 
entsprechender const-Zeiger verhält.

Hier zum Unterschied zwischen String bzw. als String verwendetem Array:
1
#include <stdio.h>
2
#include <string.h>
3

4
int main(int argc, char ** argv) {
5
  int len, size;
6
  char * ptr     = "ledaus";
7
  char   str1[]  = "ledaus";
8
  char   str2[7] = "ledaus";
9
  
10
  len   = strlen(ptr);
11
  size  = sizeof(ptr);
12
  printf("%s %d %d\n", ptr   , len, size);
13

14
  len   = strlen(str1);
15
  size  = sizeof(str1);
16
  printf("%s %d %d\n", str1  , len, size);
17

18
  len   = strlen(str2);
19
  size  = sizeof(str2);
20
  printf("%s %d %d\n", str2  , len, size);
21

22
  return 0;
23
} // main()

Die entsprechenden Ausgaben lauten auf einem x86-64 mit 64Bit-Linux, 
einmal als 64 Bit-Anwendung und einmal als 32 Bit-Anwendung kompiliert:
1
aschweig@bouvier:~/cpp> gcc -m32 -o string string.c
2
aschweig@bouvier:~/cpp> ./string
3
ledaus 6 4
4
ledaus 6 7
5
ledaus 6 7
6
aschweig@bouvier:~/cpp> gcc -o string string.c
7
aschweig@bouvier:~/cpp> ./string
8
ledaus 6 8
9
ledaus 6 7
10
ledaus 6 7
#5977633
Lesenswert?

Sepplhuber schrieb:
> Nein bei Black sind sie aus :(
>
> Also sehe überhaupt nichts mehr

ja natürlich. wie sollte eine led aussehen, die schwarz leuchtet?

Sepplhuber schrieb:
> if (incoming == "ledaus")
>     {
>       leds[0] = CRGB::Black;
>       FastLED.show();
>       Serial.println("Led´s ausgeschaltet");
>       }
>       if (incoming == "start")
>       {
>       leds[0] = CRGB::Green;
>       FastLED.show();
>       Serial.println("you started the demo routine");
>       }

gehe das mal durch und denke nach. wir gehen in die schleife rein, wenn 
incoming == ledaus. wenn dem so ist, kommt der vergleich, ob incoming 
denn == start wäre. geht das überhaupt?

und zur optimeirung: setze erst alle leds[0] bis leds[1000] und mache 
danach ein FastLED.show().
#5977678
Lesenswert?

Sven A. (quotschmacher)

>gehe das mal durch und denke nach. wir gehen in die schleife rein, wenn
>incoming == ledaus. wenn dem so ist, kommt der vergleich, ob incoming
>denn == start wäre. geht das überhaupt?

Doch, es kommt zu dem vergleich. Noch einer, der sich durch die 
Scheißformatierung verwirren läßt. War doch schon kurz vorher geklärt.
#5977686
Lesenswert?

Peter D. schrieb:
> Dirk B. schrieb:
>> Es werden nur 5 Zeichen gelesen.
>
> Meine Frage war eher, landet dann das 6. Zeichen im 2. String oder wird
> es übersprungen?

Ja. Denn es ist ja ein gültiges Zeichen für %5s


> Dirk B. schrieb:
>> andernfalls
>> wird garnichts geschrieben.
>
> Also muß ich vorher das erste Byte nullen, sonst steht noch der alte
> String drin.

Nein, du mußt den Rückgabewert von sscanf auswerten.
Der gibt an, wieviel Formate gelesen wurden. Bei deinem Formatstring 
wäre das 2.
Gast #5978406
Lesenswert?

"Es gibt keine if-Schleifen, sondern nur if-Abfragen!"

Der Satz ist aber auch quatsch. Mit "if" wird nichts abgefragt, sondern 
es wird eine Bedingung geprüft.

Unter Abfragen verstehe ich z.B. so etwas:  taster = PIND && (1<<3);
Oder: spannung = analogRead(A0);
#5978572
Lesenswert?

Stefanus F. schrieb:
> "Es gibt keine if-Schleifen, sondern nur if-Abfragen!"
>
> Der Satz ist aber auch quatsch. Mit "if" wird nichts abgefragt, sondern
> es wird eine Bedingung geprüft.
>
> Unter Abfragen verstehe ich z.B. so etwas:  taster = PIND && (1<<3);
> Oder: spannung = analogRead(A0);

Öhm, doch. If fragt schon ab. Heißt ja „Wenn“.
Deine Abfragen sind keine Abfragen sondern Zuweisungen ;)
Gast #5978580
Lesenswert?

M. K. schrieb:
>>taster = PIND && (1<<3);
> Deine Abfragen sind keine Abfragen sondern Zuweisungen ;)

Der linke Teil ja, der rechte Teil ist die Abfrage.

If macht für mich nur einen Test auf etwas, das vorher abgefragt oder 
berechnet wurde. In Assembler heisst der entsprechende Befehl bei 
einigen Mikrocontrollern sogar "tst" (siehe 
http://www.keil.com/support/man/docs/armasm/armasm_dom1361289913099.htm), 
nicht "query".

Herrlich, wie uneindeutig unsere Sprache ist. Den Deutschlehrern wird 
nie langweilig. Stell Dir mal vor, wir würden uns im echten Leben (im 
Beruf) ebenso an einzelnen Worten festbeißen... nee, besser nicht.

Ja, ich weiß, dass ich damit angefangen habe.
#5978688
Lesenswert?

Dirk B. schrieb:
> Ja. Denn es ist ja ein gültiges Zeichen für %5s

So, ich hab es jetzt auf sscanf umgestellt. Wenn der erste String in den 
2. Puffer überläuft, ist das egal, da dann ja der erste schon falsch 
ist.
Beachten muß man, wenn der String nur Whitespaces beinhaltet, wird nicht 
0 zurück gegeben, sondern EOF. Man prüft daher besser, ob die Anzahl 
stimmt, z.B. 3 ist.
Tricky ist außerdem, einen Pufferüberlauf zu verhindern.
Hier hab ich die Lösung gefunden:
https://medium.com/@hauyang/convert-int-into-string-with-c-macro-125eeaa71600
Der Code:
1
#define CMD_SIZE        19              // for sscanf, decimal number only !
2
#define PAR_SIZE        19
3

4
typedef char cmd_str_t[PAR_SIZE+1];
5
typedef char par_str_t[PAR_SIZE+1];
6

7
#define STR_INDIR(x) #x
8
#define STR(x) STR_INDIR(x)
9
#define CMD_FMT                 "%" STR(CMD_SIZE) "s"
10
#define PAR_FMT                 "%" STR(PAR_SIZE) "s"
11
// ..
12
  cmd_data.args = sscanf_P(buf, PSTR(CMD_FMT PAR_FMT "%g"), cmd_data.cmd, cmd_data.par, &cmd_data.val);

sscanf sieht zwar eleganter aus gegenüber strtok, erfordert aber 
deutlich mehr Gehirnschmalz, um es auch sicher zu machen.
#5978695
Lesenswert?

Stefanus F. schrieb:
> Der linke Teil ja, der rechte Teil ist die Abfrage.

Öhm...auch nicht. Der rechte Teil ist einfach nur eine Verknüpfung. 
Abgefragt wird da nix. Du hast hier sicher die Pin-Abfrage im Kopf nach 
dem Schema
1
if(PINB && (1 << PB0))

if fragt ja nur, ob der Ausdruck/die Bedingung wahr ist. Ist die 
Bedingung wahr wird der folgende Befehl oder Block abgearbeitet, ist die 
Bedingung nicht war wird der folgende Befehl oder Block übersprungen.

If prüft also nur, ob die Bedingung wahr ist oder nicht und prüfen kann 
man auch durch das nette Wort Abfragen ersetzen. Und in C wird jeder 
Wert, der nicht 0 ist, als wahr betrachtet bzw. jeder Wert, der 0 
entspricht, wird als nicht wahr betrachtet.

Wie gesagt, das Schlüsselwort if ist ja nicht vom Himmel gefallen, es 
ist eine Abfrage. ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren