text in Char Array finden

Hi,

jetzt bräuchte ich wieder mal die Hilfe von euch C-Experten.

Ich sende über UDP verschiedene "Botschaften" an den Arduino.
Die Botschaften möchte ich nach einer bestimmten Zeichenfolge durchsuchen, und dann abhängig vom Inhalt unterschiedliche Aktionen ausführen.

Ich als C-Laie kenne jetzt nur die Möglichkeit das CharArray in einen String zu wandeln und den dann zu durchsuchen:

String str1;
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    str1 = String(packetBuffer);
     
       if(str1.indexOf("Befehl") > -1) {
       .
       .
       }

Kann man das auch ohne die Wandlung in einen String machen?

Mein Endziel allerdings wäre es folgendes zu senden: "Befehl x y" wobei x und y Zahlen sein sollen.
Im Arduino sollten dann die beiden Zahlen im Integerformat als Parameter zum Befehl übergeben werden.

guckst du strstr

Aber wenn du die Sendeseite auch im Griff hast:
Ein Arduino ist keine Textverarbeitungs-EDV sondern ein µController.
Denk dir doch ein einfacheres Protokoll aus. ( 1 Buchstaben-Befehle können direkt in switch cases verarbeitet werden )

hk007:
Kann man das auch ohne die Wandlung in einen String machen?

Ja, natürlich.

Meine Meinung:
Wenn Du für einen Mikrocontroller programmierst, dann solltest Du überhaupt keine String-Objekte verwenden! Noch dazu, weil die String-Objekte in Arduino fehlerhaft implementiert sind und die Verwendung unter bestimmten Bedingungen (wohlgemerkt bei fehlerfreiem Code!) ruckzuck den gesamten freien RAM-Speicher aufbrauchen kann, so dass das Programm dann durchdreht. Stringobjekte unter Arduino zu verwenden ist eine Fehlerquelle ersten Ranges für die Programmierung von nichtfunktionierenden Programmen.

Dein packetBuffer dürfte ein char-Array sein, und wenn ein solches irgendwo mit einem Nullzeichen abgeschlossen ist, dann ist es quasi ein C-String, auf den Du die Stringfunktionen der C string-Standardlibrary anwenden kannst:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html
Z.B. suchen im C-String mit strstr().

Im Endeffekt mußt Du Dir als erstes ein Übertragungsprotokoll überlegen, was und wie es übertragen werden soll.

Das können Strings sein, z.B. kannst Du den Puffer ab Pufferstart mit Zeichen des Strings füllen, ein Nullzeichen dranhängen, dann kann der übertragene packetBuffer direkt wie ein C-String mit Funktionen der Standardlibrary behandelt werden.

Du kannst Startzeichen und Endezeichen aus dem Steuerzeichenbereich festlegen, wenn Strings im Puffer stehen sollen.

Du kannst den Puffer aber auch als Integer-Array behandeln, wobei der Zeiger auf das erste Zeichen im packetBuffer dann als erstes Zeichen eines Integer-Arrays betrachtet wird, mit dem Protokoll: Im ersten Integer steht die Anzahl der nachfolgenden Integerwerte, in den nachfolgenden Speicherstellen dann die übertragenen Werte.

Wenn Du Dir ein für Deine Zwecke passendes Übertragungsprotokoll ausgedacht hast, in dem alle notwendigen Werte übertragen werden können, muß es nur noch codiert werden. Wenn die übertragenen Werte immer denselben Aufbau haben und immger gleich viele Werte und immer in derselben Reihenfolge reinkommen, kann der Code sehr einfach sein. Und wenn ganz viele verschiedene Daten, mit unterschiedlichem Aufbau, unterschiedlicher Länge, in unterschiedlicher Anzahl und verschiedener Reihenfolge übertragen werden sollen, kann das Übertragungsprotokoll auch ziemlich komplex werden.

Hi,

ok. Also mal mit meinen eigenen Worten zusammengefasst, was ich da rausgelesen habe: (Verbessert mich, wenn es nicht stimmt)

Es gibt zwei verschiedene Arten von Strings.
A.)
String-Objekte, die es zu vermeiden gilt, und die ich verwendet habe, um mit "string.indexOf" eine Zeichenkette zu erkennen.
B.)
CharArrays, auch C-Strings genannt. Dafür ist der angesprochenen strstr-Befehl gedacht.
Muss ich mir mal genauer ansehen.

Denk dir doch ein einfacheres Protokoll aus. ( 1 Buchstaben-Befehle können direkt in switch cases verarbeitet werden )

Ja, du hast recht. Damit wär es relativ einfach.
Aber ich habe folgendes vor:
Ich möchte über Ethernet das Eeprom dynamisch auslesen. Also die Anfangs- und auch die Endadresse des auszulesenden Bereiches mit übergeben.
Dafür dachte ich, dass ich einen Befehl und dann, durch Leerzeichen (vllt. auch durch Komma o.ä.) getrennt, zwei Zahlen mitgebe.
Also etwa so: "ReadEeprom 0 1024"

R<0000,1024>
wäre - für einen Arduino - deutlich leichter zu lesen :wink:

... und bräuchte nicht mal strstr() .

Künstler kämen sogar ganz ohne char arrays aus, und bilden die Zahlen gleich aus den einzeln gelesenen Buchstaben...

Hey,

gute Idee.
Und auslesen kann ich dann mit chararray[0] usw...oder?

Künstler kämen sogar ganz ohne char arrays aus, und bilden die Zahlen gleich aus den einzeln gelesenen Buchstaben...

OK, da zähl ich mich wirklich nicht dazu 8)

Gängige Protokolle funktionieren prinzipiell auf drei Arten: Entweder haben sie eine fest definierte Übertragungslänge, sie haben einen header, der die übertragungslängen sowie die einzelnen befehle definiert oder sie haben ein stopzeichen, dass die einzelnen Übertragungen beendet. Nachdem ein arduino in seiner loop-schleife tendenziell prozedural abläuft bieten sich alle drei Möglichkeiten an.

Möglichkeit eins:
Du möchtest drei werte übermitteln:

  • Wert1, Ganzzahl, minimum 0, maximum 200.
  • Wert2, Ganzzahl, minimum -100, maximum +200
  • Wert3, Dezimalzahl, minimum -145,99, maximum +999,00, zwei dezimalstellen

Also muss man dem Arduino jetzt drei dinge erklären:

  • Maximale Länge Wert1 = 3
  • maximale Länge Wert2 = 4
  • maximale Länge Wert3 = 7

Möglichkeit zwei:
Du möchtest beliebig viele werte beliebiger länge übermittel:

Der Arduino muss also erstmal mit Infos gefüttert werden:

  • Anzahl der Werte
  • Länge der Werte
  • Länge der jeweiligen Werte
  • Anzahl der Kommandos, die mit diesen Werten arbeiten
  • die einzelnen Kommandos

Diese Daten nennt man Headerdaten. Wenn du diese Daten überträgst, musst du anschließend nur noch die Nutzdaten, also die eigentlichen Werte übertragen

Möglichkeit drei:
Du möchtest einen bestimmten Wert beliebiger länge übermitteln:
Im Arduino bestimmst du ein Stoppzeichen, nachdem die Übertragung als vollständig angesehen wird und der loop weiter ausgeführt wird. Dann lässt du ihn auf das stoppzeichen warten und solange es nicht kommt und eine Übertragung stattfindet, läd er die daten in einen Puffer.

Bei allen drei möglichkeiten sollte man die Platzsparendste Methode der Übertragung wählen: den char. 8-Bit länge, ein übertragenes zeichen kann bereits 256 Werte abbilden. ein zweites und es sind schon 65535 und so weiter. Plus und Minus-, sowie Dezimalwerte sind nur eine Sache der Länge und des 0-Punkts der jeweiligen charkette... sehr elegant und effizient, gerade wenn man einen protokollheader benutzt, da beim arduino eh ein char ankommt. Im nächsten Schritt könnte man sich dann mit Bitshifting auseinandersetzen, um auch noch die letzten bits overhead raus zu bekommen.

Morgen (oder eben später;)) mach ich noch ein paar Codebeispiele dazu, es sei denn, jemand anderes bietet sich an. Ich geh jetzt ins Bett.

Gute Nacht :slight_smile:

Hi,

ich habs jetzt so gemacht wie von michael_x vorgeschlagen:

R<0000,1024>

Über das "R" erkenne ich die Funktion, und die beiden Werte stecken dann in den Zeichen 2-5, sowie 7-10.
Also Protokoll mit fester Länge.

Danke an alle/hk007

Klar kann man. z.B. mit einem Zustandsautomaten. Beispiel hier: Flexible Sweep | Blinkenlight

???
Kann man was?

Ja, hab ich auch nicht so verstanden was ich in dem Link finden soll :~

Na die Antwort auf die original Frage:

Ich als C-Laie kenne jetzt nur die Möglichkeit das CharArray in einen String zu wandeln und den dann zu durchsuchen: Kann man das auch ohne die Wandlung in einen String machen?

Du solltest dein Marketing etwas optimieren, Udo.

z.B. "Zielgruppenspezifischer": Wer nach einer "subString Funktion ohne String" fragt, kann wohl kaum deine Verdienste bei Frquenzmessungen wirklich würdigen.

Meine Zielgruppe sind Leute die nicht nach 10 Zeilen aufhören zu lesen. Er will einen String parsen ohne ihn einzulesen. Genau das tue ich in dem Experiment auch. Allerdings muß man dazu schon etwas runterscrollen.

Ich hab mir deine Abhandlung im Telefonbuchformat auch durchgelesen, nur etwa ab der Hälfte wusste ich nicht mehr warum... ist wie mit der kirche ums dorf zu fahren.

Wenn Du meinst. Zustandsautomaten zum Stringparsen sind aber seit mehr als 30 Jahren "State of the Art". Wenn Du das für zu kompliziert hältst, dann ist das eher Dein Problem.

Zustandsautomaten zum Stringparsen sind aber seit mehr als 30 Jahren "State of the Art".

Das bestreitet keiner, aber Leute die nicht zu deiner Zielgruppe gehören, ändern lieber den String, damit ein kleiner aber verständlicher 3-Zeiler den Text auswerten kann.

Ob du das als Zustandsau-tomaten bezeichnest, wenn ein Zwischenergebnis gespeichert wird, interessiert viele der hier Anwesenden wenig, fürchte ich.

Ich habe schon verstanden, daß Dir meine Artikel nicht gefallen. Ob Du für die Mehrheit sprichst wage ich zu bezweifeln wenn ich mir meine Seitenstatistik so anschaue.

Kritikfähigkeit ist keine deiner Stärken, oder?

Udo, deine Artikel gefallen mir, und ich habe auch schon mein Teil zu deiner Seitenstatistik beigetragen.
Eine Abstimmung, ob dein Beitrag in diesem Thread für den OP oder andere Interessierte hilfreich war, brauchen wir nicht, glaube ich.

Ich habe auch nichts dagegen, dass du ein wenig Blinkenlight-Reklame machst, ganz im Gegenteil: Danke, dass du mich mal draufgestossen hast, es sind sehr lehrreiche Sachen, für viele verschiedene Verständnis-Level.

Die Zustandsau-tomaten nehm ich auch gern wieder raus, wenn du blöde Späße nicht nur geschmacklos, sondern auch beleidigend finden solltest.
(Auch hier, selbstverständlich.)