Parsing a string with separators ?

Can anybody please help me out.. Im scratching my head for several days now trying to parse a string.

The story, i would like to parse a string coming from x-simulator.de plugin software (rfactor racing game) and would like to display it on a lcd screen. The string contains stuff like the RPM , the speed and other usefull information which is send serialy to the arduino.

The string has a start byte, the data separated with ; and ends with !
For example:
#R17500;S120;L1;P23!

The number of field can vary so is the size for example of the RPM..

Thanks in advance

You could write your own parser for this. It's not that difficult. But, the sscanf function has already been written, tested, and optimized, for you. Easier to just use it.

http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/

But does sscanf support a varying number of fields ?

Can anybody please help me out.. Im scratching my head for several days now trying to parse a string.

...

The string has a start byte, the data separated with ; and ends with !
For example:
#R17500;S120;L1;P23!

Your string could be thought of as:
START_TAG IDENTIFIER VALUE DELIMITOR IDENTIFIER VALUE END_TAG

You could parse the string in accordance with this scheme:
1 Look for START_TAG
2 Look for IDENTIFIER
2:1 - Select correct current target value
3 Manipulate current target value until a DELIMITOR or END_TAG is read
3:1 - If one found a DELIMITOR goto 2
3:2 - If END_TAG was found, finalize process, and use recieved data

//PSEUDOCODE IN COMMENTS
//when string is vailable:
  //read char
    //switch (char)
      //case START_TAG:
        //prepare datastructures for parsing input
      //case END_TAG:
        //end datastructures, use results
    //if (isIdentifier(char))
      //set current target value in accordance with the IDENTIFIER
      //while (true) 
        //read char
        //if (char!=DELIMITOR && char!=END_TAG)
          //manipulate current target value
        //else break;

Hi, thanks for the suggestions...

I came up with this ...

I'm sure i made some stupid mistakes with pointers, but it seems to work ( for the moment :wink: )

#include <LiquidCrystal.h>
#include <stdio.h>
#include <string.h>

#define MAX_LINE 32

char line[MAX_LINE + 1];

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

struct mdata{
char rpm[8];
char gear[4];
} rfactor;

void setup()
{
lcd.begin(16, 2);
Serial.begin(9600);
}

void loop()
{
if (lineAvailable(MAX_LINE,line))
{
Analyze_String(line);
Serial.print(" Found RPM: ");
Serial.println(rfactor.rpm);
lcd.setCursor(0,1);
lcd.print(rfactor.rpm);

Serial.print(" Found GEAR: ");
Serial.println(rfactor.gear);
lcd.setCursor(0,0);
lcd.print(rfactor.gear);

}
//do something other than waiting for serial transfer
}

boolean lineAvailable(int max_line,char *line)
{
int c;
static int line_idx = 0;
static boolean eol = false;
static boolean start = false;
static boolean mstop = false;

if (max_line <= 0) // handle bad values for max_line
{
eol = true;
if (max_line == 0)
line[0] = '\0';
}
else // valid max_line
{
if (Serial.available() > 0)
{
c = Serial.read();

if (c != -1 ) // got a char -- should always be true
{
if ( c == '!' ) start = true;
if ( c == '#' ) mstop = true;

if (c == '\r' || c == '\n')
eol = true;
else
if ( start )

line[line_idx++] = c;

if ( mstop )
eol = true;

if (line_idx >= max_line)
eol = true;

line[line_idx] = '\0'; // always terminate line, even if unfinished
}

if (eol)
{
line_idx = 0; // reset for next line
eol = false; // get ready for another line
start = false;
mstop = false;

return true;
}
else
return false;
}
}
}

int Analyze_String(char line[]){
const char *ptr = line;
char field [ 32 ];
int n;
while ( sscanf(ptr, "%31[^;]%n", field, &n) == 1 )
{
switch(field[0]) {
case 'R':
strcpy(rfactor.rpm, field);
break;

case 'G':
strcpy(rfactor.gear, field);
break;

}
// delay(10);
ptr += n; /* advance the pointer by the number of characters read */
if ( ptr != ';' )
{
break; /
didn't find an expected delimiter, done? /
}
++ptr; /
skip the delimiter */
}
return 0;
}

String example:
!;R 17500;G 2;S 151;L 2;P 10;#

A newbie here with the Arduino. I have been looking around the net in hopes of finding exactly what this post is about. If the original poster ever comes back and see this please explain more about how to set this up. Very much interested in this.

Have a look at the TextFinder library in the playground: Arduino Playground - TextFinder

It includes an example sketch that parses serial data of the form:
H 12,-345,678!
Into an integer array that is easy to access.

The code in the example would need to be modified to parse the message format posted above but using TextFinder should be a lot easier than coding this from scratch.