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.
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.
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.
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_ti=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.
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");
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!
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.
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_ti=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.
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.
Die strings sollten im Vorfeld geparst und durch enums ersetzt werden.
Damit lassen sich dann ggf. switches realisieren unnd unnötige string
compares vermeiden.
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:
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.
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 ...
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!
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?
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):
Stefanus F. schrieb:> In Java und C# könntest du diese if-Kette durch switch-case ersetzen.> leider geht das in C++ nicht.
Quatsch: In C++ kannst Du alles machen, was in C geht.
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.
Brummbär schrieb:>> In Java und C# könntest du diese if-Kette durch switch-case ersetzen.>> leider geht das in C++ nicht.> Quatsch: In C++ kannst Du alles machen, was in C geht.
Switch-case mit String können C und C++ nicht. Java und C# können das
aber.
Brummbär schrieb:> Stefanus F. schrieb:>> In Java und C# könntest du diese if-Kette durch switch-case ersetzen.>> leider geht das in C++ nicht.>> Quatsch: In C++ kannst Du alles machen, was in C geht.
In C geht das auch nicht (wegen der Strings, das mag Switch nicht)
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++.
Brummbär schrieb:> Ist ein direkter "==" bei einem String möglich?
Bei std::string ja, bei C-Strings nicht (in dem Sinn als ersatz für
strcmp())
> Das geht zwar in einigen Skriptsprachen, aber nicht in C/C++.
Bei C geht es definitiv nicht.
Brummbär schrieb:
Das geht zwar in einigen Skriptsprachen, aber nicht in C/C++.
Das geht zwar in einigen Skriptsprachen, aber nicht in C/C++.
Mein Code läuft einwandfrei nur halt mit den vielen IF abfragen, ich
denke Arduino ist C++
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.
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
intmain(intargc,char**argv){
5
intlen,size;
6
char*ptr="ledaus";
7
charstr1[]="ledaus";
8
charstr2[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
return0;
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:
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().
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?
Dirk B. schrieb:> andernfalls> wird garnichts geschrieben.
Also muß ich vorher das erste Byte nullen, sonst steht noch der alte
String drin.
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.
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.
Jens G. schrieb:>> Doch, es kommt zu dem vergleich. Noch einer, der sich durch die> Scheißformatierung verwirren läßt. War doch schon kurz vorher geklärt.
das der vergleich kommt wollte ich auch nicht anzweifeln, nur, dass der
nie zutreffen kann.
Sven A. schrieb:> das der vergleich kommt wollte ich auch nicht anzweifeln, nur, dass der> nie zutreffen kann.
Und damit liegst du immernoch falsch. Schau dir die fehlerhafte
Formatierung deines zitierten Codeschnippsels nochmal an.
Sven A. schrieb:> Sepplhuber schrieb:>> if (incoming == "ledaus")
...
>> gehe das mal durch und denke nach. wir gehen in die schleife rein,http://if-schleife.de/
(sorry, ist Freitag ;-))
"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);
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 ;)
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.
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 !
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. ;)
M. K. schrieb:> Wie gesagt, das Schlüsselwort if ist ja nicht vom Himmel gefallen, es> ist eine Abfrage. ;)
Wenn du meinst. Solange wir beide das Schlüsseldorf sinnvoll benutzen
können (woran ich nicht zweifle) ist mir egal, wie wir es bezeichnen.