Mit Kommas getrennten String auslesen

Hallo Zusammen,

langsam verzweifel ich und bräuchte etwas Hilfe.

Ich lese von einer Webseite einen String aus, die Werte sind mit Kommata getrennt.
Ich möchte hier raus die einzelnen Werte aus String extrahieren.

...     
int vonPos = line.indexOf("[");
int bisPos = line.indexOf("]",vonPos+1);
String Werte = (line.substring(vonPos + 1, bisPos));

'Werte' schaut dann so aus:
0.0,1.1,0.0,133.1,1.0,234.6,120,36,0.4,36.3,-819,0,146,0.00,0.00,0,27,0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,13819.50,12167.40,,,,,,,,50.02,,,0.0,0.0,0,0.00,0

Mit den anderen, ähnlichen Themen bin ich leider nicht zum Erfolg gekommen. (z.B. String nach Komma aufteilen - Deutsch - Arduino Forum

Vielen Dank für eure Hilfe :confused:

Es fehlen folgende Angaben:
Welcher Microcontroller,
Welche LAN-Verbindung (WLAN oder Ethernet)
bitte einen ganzen kompilierbaren Sketch.

Schau dir mal die Funktion 'strtok' an. Die ist genau für sowas gemacht.

ESP8266 über WiFi

/*
 * Basic ESP Client example, based on the ESP libraries examples
 */
 
#include <ESP8266WiFi.h>
#include <Blynk.h>

const char* ssid     = "xxx";
const char* password = "xxx";
const char* host = "192.168.1.113";

WiFiServer server(80); 
BlynkTimer timer;

String LeistungHeute;
String LeistungGesamt;
String NetzbezugAktuell;


void setup() {
  Serial.begin(115200);
  delay(10);
 
  // We start by connecting to a WiFi network
 
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  server.begin();

  timer.setInterval(30000, abfrage); // Updates checken
}
 
void loop() {
  timer.run();
}


void abfrage()
{
  Serial.print("connecting to ");
  Serial.println(host);
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
   
  // We now create a URI for the request
  String url = "/api/realTimeData.htm";
   
  Serial.print("Requesting URL: ");
  Serial.println(url);
   
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  // start waiting for the response             
  unsigned long lasttime = millis();
  while (!client.available() && millis() - lasttime < 1000) {delay(1);}   // wait max 1s for data
  // Read all the lines of the reply from server and print them to Serial
 
  while(client.available()){
    //char readchar = client.read();
   // Serial.print(readchar);
   

    Serial.println();
      String line = client.readStringUntil('\r');
    if (line.indexOf("{")>=0) {   // Searchstring exists?

      int vonPos = line.indexOf("[");
      int bisPos = line.indexOf("]",vonPos+1);
      String Werte = (line.substring(vonPos + 1, bisPos));
      Serial.print(Werte);

   



    }
    Serial.print(line);

    
  }
  Serial.println();
  Serial.println("closing connection");
  //delay(60000);
}

MicroBahner:
Schau dir mal die Funktion 'strtok' an. Die ist genau für sowas gemacht.

Das habe ich versucht, ich scheitere daran, char string[] = meinem String Werte zu setzen.

strtok erwartet sein Argument als char array[], nicht als String Objekt. Musst du rüber kopieren. Und die Verwendung von String Objekten wird dir irgendwann auf die Füße fallen. Gut, beim ESP vielleicht nicht gleich, aber bei Verwendung von einem z.B. Uno recht schnell.
Wenn du schon mehr Komfort suchst, nimm lieber die PString Lib.

String Objekte sind für Splitten und Konvertieren auch irrsinnig kompliziert. Mit char Arrays geht das wesentlich einfacher:

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

  char str[] = "0.0,10.1,-133.5,1234.56";
  double values[4];

  char* ptr = strtok(str, ",");
  for (double &value : values)
  {
    value = atof(ptr);
    ptr = strtok(nullptr, ",");
  }

  for (double& value : values)
    Serial.println(value);
}

void loop()
{
}

Wichtig ist dass man über das Array der Werte iteriert und nicht über den String. Sonst kann man über die Grenzen schreiben

ElEspanol:
strtok erwartet sein Argument als char array[], nicht als String Objekt. Musst du rüber kopieren. Und die Verwendung von String Objekten wird dir irgendwann auf die Füße fallen. Gut, beim ESP vielleicht nicht gleich, aber bei Verwendung von einem z.B. Uno recht schnell.
Wenn du schon mehr Komfort suchst, nimm lieber die PString Lib.

So klappt es schon mal wie ich es mir vorstelle:

char copy[200];
Werte.toCharArray(copy, 200);


char delimiter[] = ",;";
char *ptr;

// initialisieren und ersten Abschnitt erstellen
ptr = strtok(copy, delimiter);

while(ptr != NULL) {
  printf("Abschnitt gefunden: %s\n", ptr);
  // naechsten Abschnitt erstellen
  ptr = strtok(NULL, delimiter);
}

Ausgabe:

15:46:23.556 -> Abschnitt gefunden: 0.7
15:46:23.556 -> Abschnitt gefunden: 0.0
15:46:23.556 -> Abschnitt gefunden: 127.1
15:46:23.591 -> Abschnitt gefunden: 0.9
15:46:23.591 -> Abschnitt gefunden: 235.4
15:46:23.591 -> Abschnitt gefunden: 63
15:46:23.591 -> Abschnitt gefunden: 36
15:46:23.591 -> Abschnitt gefunden: 0.5
15:46:23.591 -> Abschnitt gefunden: 36.4
15:46:23.591 -> Abschnitt gefunden: -880
15:46:23.591 -> Abschnitt gefunden: 0
15:46:23.591 -> Abschnitt gefunden: 88
15:46:23.591 -> Abschnitt gefunden: 0.00
15:46:23.591 -> Abschnitt gefunden: 0.00
15:46:23.591 -> Abschnitt gefunden: 0
15:46:23.591 -> Abschnitt gefunden: 27
15:46:23.591 -> Abschnitt gefunden: 0
15:46:23.591 -> Abschnitt gefunden: 0.0
15:46:23.591 -> Abschnitt gefunden: 0.0
15:46:23.591 -> Abschnitt gefunden: 13819.50
15:46:23.626 -> Abschnitt gefunden: 12168.80
15:46:23.626 -> Abschnitt gefunden: 49.99
15:46:23.626 -> Abschnitt gefunden: 0.0
15:46:23.626 -> Abschnitt gefunden: 0.0
15:46:23.626 -> Abschnitt gefunden: 0
15:46:23.626 -> Abschnitt gefunden: 0.00
15:46:23.626 -> Abschnitt gefunden: 0

Jetzt stellt sich mir die Frage, wie komme ich an die einzelnen Werte ran, so das ich mit diesen weiter arbeiten kann.

Obwohl ich strtok auch vorziehe, kann man es aber auch mit String lösen:

String eingabe = "1,33,55,12,105,1002,66";

void teile(const String in, const char trenn) {
int16_t posA = -1, posB = 0;
String teil;
  teil.reserve(10);  // zu erwartende Länge der Teilzeichenkette
  posB = in.indexOf(trenn);
  while (posB >= 0) {
    teil = in.substring(posA+1, posB);
    // mache was damit
    Serial.println(teil);
    posA = posB;
    posB = in.indexOf(trenn,posA+1);
  }
  teil = in.substring(posA+1);
  // mache was damit
  Serial.println(teil);
}

void setup() {
  Serial.begin(115200);
  Serial.println("\nStart");
  teile(eingabe,',');
}

void loop() {}

Gruß Tommy

richie241:
Jetzt stellt sich mir die Frage, wie komme ich an die einzelnen Werte ran, so das ich mit diesen weiter arbeiten kann.

Die Antwort steht in #5: Die Werte befinden sich im Feld values[].

Oder was meinst Du?

Ich meine meine Lösung aus #6 - es funktioniert ja -
allerdings komme ich nicht an die einzelnen Werte, so das ich dieses zB als String wegschreibe :frowning:

Das heißt du versteht den Code überhaupt nicht und willst eine komplett fertige Lösung. Was hier gezeigt wird sind Prinzip-Beispiele, die du für deinen Bedarf anpassen musst

@TO: Was willst Du denn überhaupt mit den Teilstrings machen?

Gruß Tommy

Serenifly:
Das heißt du versteht den Code überhaupt nicht und willst eine komplett fertige Lösung. Was hier gezeigt wird sind Prinzip-Beispiele, die du für deinen Bedarf anpassen musst

Entschuldigung - ich bin Anfänger und kein wirklicher 'Programmierer'.
Ich brauche die Funktion zum Auslesen meiner PV Wechselrichterdaten und ich hangel mich
mit dem ESP8266 und Arduino so durch, damit ich klar komme.

Nicht falsch verstehen, ich habe gedacht ich könnte hier eine (einfache) Lösung für mein Problem erhalten.
Ich würde es natürlich selber Lösen, allerdings ist mein Wissen dazu nicht groß genug noch liegt mein Fokus darauf, "Programieren zu lernen"

Danke für eure Mühe

Tommy56:
@TO: Was willst Du denn überhaupt mit den Teilstrings machen?

Gruß Tommy

Diese sollen auf einem Display und/oder auf einem internen Websever wiedergegeben werden.

Dann brauchst du die Werte also gar nicht unbedingt in Zahlen zu konvertieren. Alle Lösungen die dir hier gezeigt wurde geben die Teil-Strings auf der seriellen Schnittstelle aus. Damit kannst du genauso was anderes machen

Serenifly:
Dann brauchst du die Werte also gar nicht unbedingt in Zahlen zu konvertieren. Alle Lösungen die dir hier gezeigt wurde geben die Teil-Strings auf der seriellen Schnittstelle aus. Damit kannst du genauso was anderes machen

Ich wäre dir sehr dankbar wenn du mir sagen könntest, wie ich z.B. den ersten, zweiten, dritten usw. einzeln abbilden kann

richie241:
Nicht falsch verstehen, ich habe gedacht ich könnte hier eine (einfache) Lösung für mein Problem erhalten.
Ich würde es natürlich selber Lösen, allerdings ist mein Wissen dazu nicht groß genug noch liegt mein Fokus darauf, "Programieren zu lernen"

Dann hast Du wohl ein Problem.
Wenn Du nicht lernen willst, wie man Auto fährt darfst Du nicht fahren.
Wenn Du nicht lernen willst, wie Du Dein Auto reparierst, musst Du einen Dienstleister (Werkstatt) bezahlen.

Warum soll das in der Programmierung anders sein?

Da, wo der Wert ausgegeben wird, kannst Du doch Deine schwammig formulierte Verwendung rein bauen.
lcd.print ist stark verwand mit Serial.print.

Dass Du einen Webserver, ohne etwas zu lernen, hin bekommst wage ich zu bezweifeln.

Gruß Tommy

Edit: Um Gerüchten vorzubeugen: Ich bin kein Dienstleister.

https://forum.arduino.cc/index.php?topic=396450.0

Dein Link ist defekt.

Gruß Tommy

wow! seit wann wandelt das Forum es selbst um?

https://forum.arduino.cc/index.php?topic=396450.0