Is there an alternative to strtok_r in extracting words from char? 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


  "=", " ", "&amp;"


Code:

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


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

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

  p = strtok_r(NULL, "=", &amp;i);
  // Get PASS
  p = strtok_r(NULL, " ", &amp;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 &lt;Regexp.h&gt;

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

    void setup() {
      ms.Target(payload);
      char match_result = ms.Match("ssid=(.*)&amp;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() {}
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 &lt; 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 &amp; characters, and if a &amp; needs to appear in one of the values, it should be percent encoded (where the &amp; would appear as %26, and would need to be decoded afterwards).

However, that wasn't your question...