How to parse arduino string with different delimiters?

Hello guys, today i came with a question about how to split a string like this with different variables with something like this:

String input = "{a:9999;b:8888;c:7777;d:1111}";

into something like this:

string a = 9999;
string b = 8888;
string c = 7777;
string d = 1111;

I thought that i could use functions like this: startsWith() and endsWith() but this only gives a boolean right? and i want to store the data between a: and ;

I added the { and the } to make sure that the all the data inside the { } is received correctly.

I hope you can help me

Thanks

Use C strings, instead of String Objects. then use strtok() to split the string into different parts.

and i want to store the data between a: and ;

Should be fairly easy to do, similar to the below test code. You would find the positions (indexOf(':')) of the : and ; then capture the data in between. Then find the positions of the next : and ; then again capture the data in between. Note the second find starts at the previous found position +1.

//zoomkat 11-12-13 String capture and parsing  
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data 

String readString; //main captured String 
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
      
      Serial.println();
      Serial.print("captured String is : "); 
      Serial.println(readString); //prints string to serial port out
      
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle); 
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
      
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}
1 Like

The parse example in serial input basics may be useful. It illustrates the use of strtok()

...R

Regardless of which approach you use, it is probably conceptually easier to do the parsing in two stages. Get the tokens "a:9999", "b:8888", "c:7777", and "d:1111". Then, parse each of those tokens.

Thanks all for you help, i was able to do it using strtok function, i left you the code if someone else have the same question and if you have a suggestion to make the code works better it will be welcome:

#include <string.h>


char input[] = "{a:9;b:8;c:7;d:1}"; //Input
const char del[] = "{}abcd:;"; //Delimiters 
char *token,*ok1,*ok2; 
int i=0;
char *array[3]; // Number of variables to save
int loc1,loc2;
const char str3 = '{';
const char str4 = '}';
   

void setup() {
  Serial.begin(9600);
  Serial.print("Input: "); //Display the input
  Serial.println(input);
  
 
  ok1=strchr(input, str3); // Check that { exist on string
  ok2=strchr(input, str4); // Check that } exist on string
  
  
  if (ok1!=NULL && ok2!=NULL) //Checks char has { and }, i do this because i will send different kind of messages using { and } to indicate one type.


  {
  
   token = strtok(input, del);
   
  
 Serial.println("Splitted");
   while( token != NULL ) 
   {
     array[i++] = token;
     Serial.println(token); //Print all the tokens
     token = strtok(NULL, del);
   }
  
  Serial.println("Saved");
  for (i=0;i<=3; ++i) {
    Serial.println(array[i]);  //Print the saved value
  }
  }
  
}

void loop() {
 
  
}
1 Like

i made function formy purpose, but that is "String"

int *getDelimeters(String DelString, String Delby) {
 static int Delimeters[3];//important!!! now much delimeters;
 int i = 0;
 while (DelString.indexOf(Delby) >= 0) {
   int delim = DelString.indexOf(Delby);
   Delimeters[i] = (DelString.substring(0, delim)).toInt();
   DelString = DelString.substring(delim + 1, DelString.length());
   i++;
   if (DelString.indexOf(Delby) == -1) {
     Delimeters[i] = DelString.toInt();
   }
 }
 return Delimeters;
}

int *RevertInt= getDelimeters(StringWithDelimeter, ":");

then use it:

Serial.println(String(RevertInt[0]));
RevertInt[1]
RevertInt[2]

I have just published a SafeStrings library that does tokenizing and parsing of user input.
see https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html

The main advantage of SafeStrings over Arduino strings is better debugging and no heap fragmentation (ever)
Plus nice tokenizing methods