1

The task, in char, I get some data that I have to parse into parts.

In this case, I use strtok_r, which finds identifiers like

"=", " ", "&"

Code:

char payload[70] = "GET /wifi?ssid=MyWiFi&pass=123456789 HTTP 11";
char *p;
char *i;


void setup() {
  Serial.begin(15200);
  Serial.println("Load");

  p = strtok_r(payload, "=", &i);
  // Get SSID
  p = strtok_r(NULL, "&", &i);
  Serial.println(p);

  p = strtok_r(NULL, "=", &i);
  // Get PASS
  p = strtok_r(NULL, " ", &i);
  Serial.println(p);
}

void loop() {}

Result:

Load MyWiFi 123456789

This works, but as soon as I add the characters strtok_r works on to the ssid = or pass = value, it stops working, outputting the cropped data.

These characters can be in the name of any WiFi network or the generated password.

Tell me, are there strtok_r analogues, where instead of a single character I can insert a whole phrase?

For example, so that he finds the beginning of ssid by the tag "ssid=", and finishes before "pass=".

Resolved.

Thank you all for your help!

I studied both options from @Majenko and @user7761803. All of them came in handy in various parts of the code.

Perhaps someone will use the Regexp library to parse such data. Here is example:

    #include <Regexp.h>

    char payload[60] = "ssid=MyWifi&pass=ukLPm&I*uwlm HTTP";
    char ssid[25], pass[25];

    void setup() {
      ms.Target(payload);
      char match_result = ms.Match("ssid=(.*)&pass=(.*) H", 0);
      if(match_result == 1) {
       // Get SSID
       ssid = ms.GetCapture(regexp_var.buffer, 0);
       // Get PASS
       pass = ms.GetCapture(regexp_var.buffer, 1);
      }
    }

    void loop() {}
3

The function you are looking for is strstr(), which takes two strings, and returns a pointer to where the second string appears in the first (or NULL if it doesn't appear).

You could use it something like this:

void setup() {

    Serial.begin(15200);
    Serial.println("Load");

    char *p = strstr(payload, "ssid=");
    char *q = strstr(payload, "pass=");
    char *r = strstr(payload, " HTTP");

    char *ssid = NULL;
    char *pass = NULL;

    if (p == NULL || q == NULL || r == NULL) {
        // One or other (or both) missing - what to do?
    } else {
        *r = '\0';  // Terminate the last string

        // If this really is an HTTP query string, we don't know
        // if ssid or pass will be first
        if (p < q) {    // Terminate the first string
            *(q - 1) = '\0';
        } else {
            *(p - 1) = '\0';
        }

        ssid = p + 5;
        pass = q + 5;

        Serial.println(ssid);
        Serial.println(pass);
    }
}

Note, however, that your payload string looks like an HTTP query string.

These are defined so that they are split at the & characters, and if a & needs to appear in one of the values, it should be percent encoded (where the & would appear as %26, and would need to be decoded afterwards).

However, that wasn't your question...

1

The normal way of parsing such complex strings in any language is to use Regular Expressions.

Normally these are pretty heavy-weight to use, but thankfully Nick Gammon has written an Arduino implementation of regexp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.