String zerlegen und ich Zahlen umwandeln

Hallo miteinander,

ich möchte über die Serielle schnitt stelle befehle empfangen, dies Befehle muss ich dann als erstes zerlegen und aufteilen.

Das Protokoll sieht so aus.

Trennzeichen ;

Start mit dem Befehl
Folgen 5 Werte (alles Zahlen können mit Komma sein)

z.B.
Befehl;Wert1;Wert2;Wert3;Wert4;Wert5

Jetzt habe ich mir erst ein mal eine Kleien Hilfe gebaut, und die werte richtig trennen zu können, denn dann muss ich ja auch Prüfen ob alle werte angekommen sind ob diese Plausibel sind und erst dann kann ich anfangen zu arbeiten.

Daher ist die Übertragung über die Serielle Schnittstelle erst ein mal mit der Variable “text” definiert worden.

Das Programm läuft nur 1 mal durch, das ich auch was auf der Seriellen Schnittstelle sehen kann!

Ich Stolpere jedoch an ein Paar Dingen.

  1. Warum wird meine Variable “text” verändert? (von Start zum ende)
    nicht wichtig für das Programm, ich will es aber verstehen.
  2. Wie kann ich den Inhalt der Variable in eine Zahl mit Nachkommastellen wandeln?
    meine Kommastelle geht immer flöten :frowning:

Gruß Mücke

int j = 0; 

void setup() 
{
    Serial.begin(9600);
    while (!Serial) {} // Warten Sie, bis der serielle Port verbunden ist.
} 

void loop() {
  
  while (j == 1); // Ausgabe soll nur 1 mal erfolgen 
  {

    char* text = "X;1;1;100;400.5";   // Beispiel übertragung über die Serielle Schnittstelle
   
   Serial.println("#################### Start ####################");
   Serial.print("Uebertragung_Start: ");  Serial.println(text); // Alles was Uebertragen wurde 

    char* verarbeiten = text;                                   // Uebertragung in neue Variable speichern
    
    char* token = strtok(verarbeiten, ";");                     // Variablen Inhalt bei ; Trennen   
    char* Achse = token;
    
    token= strtok(0, ";");
    char* EAN = token;
    
    token = strtok(0, ";");
    char* DIR = token;
    
    token = strtok(0, ";");
    char* RPM = token;
    
    token = strtok(0, ";");
    char* PLU = token;

    float PLU_Zahl = atoi(PLU); // das komma fehlt 
//    float PLU_Zahl = atol(PLU); // das komma fehlt

    float PLU_Zahl_Rechnen = PLU_Zahl + 200;    // Testen ob es wirklich eine Zahl ist, mit Zahlen kann man rechnen :-) 

   Serial.print("Achse: "); Serial.println(Achse);               // Einzelne Werte ausgeben 
   Serial.print("ENA: ");   Serial.println(EAN);                // Einzelne Werte ausgeben 
   Serial.print("DIR: ");   Serial.println(DIR);                // Einzelne Werte ausgeben 
   Serial.print("RPM: ");   Serial.println(RPM);                // Einzelne Werte ausgeben 
   Serial.print("PLU: ");   Serial.println(PLU);                // Einzelne Werte ausgeben 
   Serial.print("PLU Zahl: ");   Serial.println(PLU_Zahl);                // Einzelne Werte ausgeben
   Serial.print("PLU Zahl Rechnen: ");   Serial.println(PLU_Zahl_Rechnen);                // Einzelne Werte ausgeben   
   Serial.print("Uebertragung_Ende: "); Serial.println(text);   // Vollstaendige Uebertragung ausgeben
   
   j++; // Zaehler fuer die Schleife hoch zaehlen
  }  // while (j == 1);

} // void loop()

Warum wird meine Variable “text” verändert? (von Start zum ende)

strtok() terminiert die Teil-Strings. Also ersetzt den Delimiter durch NULL

Wie kann ich den Inhalt der Variable in eine Zahl mit Nachkommastellen wandeln?

atoi()/atol() ist wie der Name sagt für Integer. Für Floats gibt es atof(). Wieso erwartest du dass das mit Floats geht?

5 Werte konvertieren geht ganz einfach. Man kann strtok() + atof() in eine Zeile schreiben:

char str[] = "10.0;20.5;30.2;50.1;60.8";

void setup()
{
 Serial.begin(9600);

 float value1 = atof(strtok(str, ";"));
 float value2 = atof(strtok(NULL, ";"));
 float value3 = atof(strtok(NULL, ";"));
 float value4 = atof(strtok(NULL, ";"));
 float value5 = atof(strtok(NULL, ";"));

 Serial.println(value1);
 Serial.println(value2);
 Serial.println(value3);
 Serial.println(value4);
 Serial.println(value5);
}

void loop()
{
}

Man kann das auch in einer for-Schleife machen und die Zahlen in einem Array speichern:

char str[] = "10.0;20.5;30.2;50.1;60.8";
float values[5];

void setup()
{
  Serial.begin(9600);

  char* ptr = strtok(str, ";");

  for (byte i = 0; i < sizeof(values) / sizeof(values[0]); i++)
  {
    values[i] = atof(ptr);
    ptr = strtok(NULL, ";");
  }

  for (byte i = 0; i < sizeof(values) / sizeof(values[0]); i++)
    Serial.println(values[i]);
}

void loop()
{
}

Alternativ eine while-Schleife nehmen und abbrechen wenn strtok() NULL zurück gibt. Dann muss man aber noch abfragen dass man nicht über das Array schreibt! Die obige Version passt sowohl wenn der String kürzer (dann steht einfach 0.0 in den übrigen Werten) als auch länger als das Array ist

Serenifly: strtok() terminiert die Teil-Strings. Also ersetzt den Delimiter durch NULL

Das ist richtig, jedoch arbeite ich in meinem CODE doch gar nicht mit der Variable text sondern mit der Variablen verarbeiten.

char* verarbeiten = text;

und genau deshalb wundert es mich das die Variable text verändert wird!

Serenifly: atoi()/atol() ist wie der Name sagt für Integer. Für Floats gibt es atof().

Ah das erklärt einiges.

Serenifly: Wieso erwartest du dass das mit Floats geht?

Variablentypen: Variablentyp: float Bedeutung: Fließkommazahl Beschreibung: gebrochene Zahlen Quelle: Variablen

Serenifly: 5 Werte konvertieren geht ganz einfach. Man kann strtok() + atof() in eine Zeile schreiben:

Hmm, warum sitze ich schon den ganzen tag an dem kleinen teil, und du machst das so kurzer Hand neben her? und dann noch auf eine echt schlanke und Strukturierte Art und weise, ich sogar ich verstehe? Das ärgert mich ein wenig. (Mücke nicht so kompliziert denken, arrrrrrr)

Serenifly: Man kann das auch in einer for-Schleife machen und die Zahlen in einem Array speichern:

...

Alternativ eine while-Schleife nehmen und abbrechen wenn strtok() NULL zurück gibt. Dann muss man aber noch abfragen dass man nicht über das Array schreibt! Die obige Version passt sowohl wenn der String kürzer (dann steht einfach 0.0 in den übrigen Werten) als auch länger als das Array ist

An so etwas habe ich auch schon gedacht, wenn jedoch musste ich erst mal den Rest hin bekommen, bevor ich an so was denke. Für mich ist es wichtig das ich wenig zeit benötige, welche Methode ist zeitsparender? ich gehe davon aus, die Ohne schleife, da ich dann weniger Dinge abfragen muss und jede Abfrage kostet zeit.

Danke

Gruß Mücke

char* verarbeiten = text;

Schau dir an was Zeiger sind. Verarbeiten ist nur ein Zeiger auf text. Also wird natürlich text verändert

Am besten du verwendest nicht die Zeiger-Syntax für String Konstanten, sondern machst ein Array draus. Das kannst du dann zwar immer noch einem Zeiger zuweisen, aber du kannst es nicht einfach kopieren indem du es einem anderen Array zuweist. Da kommt dann ein Fehler.

ich gehe davon aus, die Ohne schleife, da ich dann weniger Dinge abfragen muss und jede Abfrage kostet zeit.

Das ist in dem Fall egal. Was da praktisch ist hängt von der Anwendung ab. Ich mache es i.d.R. ohne Schleife da ich wie du weiß wie viele Werte ich erwarte

Lesestoff Zeiger.

Ah das erklärt einiges.

das mit den Zeiger habe ich mir schön öfters angeschaut, irgend wie bleibt das bei mir nicht hängen. Liegt vielleicht auch daran das ich mich nicht täglich mit Programmiren beschäftige. :-(

Danke euch. für die Hilfe.

Gruß Mücke

Merke Dir doch erst mal etwas vereinfacht:

Der Zeiger ist nicht der Inhalt, sondern merkt sich [u]wo[/u] dieser steht. (Beim Array wo das erste Element steht.)

Gruß Tommy

Hey Tommy,

wie das mit den Zeigern funktioniert wies ich in der Theorie, mein rissen Problem ist immer wider die schreib weisen.

Ich muss gestehen das ich sehr viel herum probiere, bis ich zum Ergebnis komme, was oft mit nur Kleinigkeiten von schreib weisen zusammen hängt. :-(

Ich bin kein Informatiker, sondern ein Kaufmann, und da kommt es durch aus mal vor das ich über 12 Monate oder länger keinen Code zu gesiecht bekomme, was zu folge hat das ich sehr viel wider vergesse :-(

Ja ich weiß das sind nicht die besten Voraussetzungen für mich.

Da auch der Code von mir wider zusammen gesetzte erweiterte und neu aufgebaute teile aus dem Internet waren, kam es dazu das ich zwar gesehen habe das ich hier mit einer Variablen arbeite doch mit dem * dabei nichts anfangen konnte, leider hatte ich dazu auch nichts im Netz gefunden, also habe ich es so gelassen.

Als ich das weg lassen wollte kam ein Fehler also las ich es dran. denn Fehler sind irgend wie doof ;-).

Gruß Mücke

jedoch habe ich schon wider angefangen mir den Link von @agmue durchzulesen.