Parse a String received

I am not much of a C programmer and have completed a big sketch except for one remaining step, namely parsing a string delimited by a comma “,”.

The string is received by the following sub:

void handle_sent_data(uint8_t data, uint16_t length) {
Particle.publish(“Data Capture”, String((char
)data));
}

I know I am receiving the correct string because I can see it on the web but how do I go about parsing it?

Here is a sample string: “%%,8,7135,4563,5687,@” I want to store the 8, 7135, 4563 and 5687 in int variables.

Any help is appreciated.

You should check out the C function strtok() for separating the string into its pieces, and atoi() to convert the string pieces to ints. There should be quite a few references to those here on the forum.

Thank you @Ric.

I looked up strtok() but it is complicated. Any chance you can direct me to a simple example for this string

“%%,8,7135,4563,5687,@” which is stored in the variable data.

Thanks again.

For non-floating point tokens you could also use sscanf().

  int a, b, c, d;
  int result = sscanf(data, "%%%%,%d,%d,%d,%d,@", &a, &b, &c, &d);

The four pecent signs represent the escaped “double percent” starting tag. The result value will provide the count of successfully parsed integers.

This also makes sure not to parse unrelated data (not part of the incoming string or strings not contained between the dilimter tags %%....@)

1 Like

you can try like this:

struct PacketData {
  int first;
  int second;
  int third;
  int fourth;
};

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

 void loop() {
  const char* inString = "%%,8,7135,4563,5687,@";
  PacketData newData;
  parsePacket(inString, newData);
  Serial.println(newData.first);
  Serial.println(newData.second);
  Serial.println(newData.third);
  Serial.println(newData.fourth);
  delay(5000);
 }

 void parsePacket(const char* str, PacketData& data) {
  char* ptr = str;         // create a pointer pointed to the first position in the string
  ptr = strchr(ptr, ',');  // move the pointer to the first comma
  ptr++;                   // move the pointer one position
  data.first = atoi(ptr);  // parse the value as an int
  ptr = strchr(ptr, ',');  // move the pointer to the next comma, etc
  ptr++;
  data.second = atoi(ptr);
  ptr = strchr(ptr, ',');
  ptr++;
  data.third = atoi(ptr);
  ptr = strchr(ptr, ',');
  ptr++;
  data.fourth = atoi(ptr);
 }

2 Likes

Thank you @ScruffR.

I am getting the error:
invalid conversion from 'uint8_t* {aka unsigned char*}' to 'const char*' [-fpermissive]

Here is my code:

void parseData(uint8_t *data, uint16_t length)
//$$,5455,0,1,0,1,1,0,^
{   
  int a, b, c, d, e, f, g;
  sscanf(data, "%%$$,%d,%d,%d,%d,%d,%d,%d,^", &a, &b, &c, &d, &e, &f, &g);

}

Thank you @BulldogLowell. I appreciate it.

To overcome that you could either declare your function as void parseData(const char* data, uint16_t length) or do a typecast in the call sscanf((const char*)data, ...).

If your string now starts with two dollar signs ($$) you will have to remove the two percent signs in your format string otherwise your string would be expected to start with "%$$....".

Thank you @ScruffR.