Есть ли альтернатива strtok_r при извлечении слов из char?

Задача, в char, я получаю некоторые данные, которые мне нужно разобрать на части.

В этом случае я использую strtok_r, который находит такие идентификаторы, как

"=", " ", "&"

Код:

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);
  // Получить SSID
  p = strtok_r(NULL, "&", &i);
  Serial.println(p);

  p = strtok_r(NULL, "=", &i);
  // Получить ПРОПУСК
  p = strtok_r(NULL, " ", &i);
  Serial.println(p);
}

void loop() {}

Результат:

Загрузить MyWiFi 123456789

Это работает, но как только я добавляю символы, над которыми работает strtok_r, к значению ssid = или pass =, он перестает работать, выводя обрезанные данные.

Эти символы могут быть в названии любой сети Wi-Fi или сгенерированном пароле.

Подскажите, есть ли аналоги strtok_r, где вместо одного символа можно вставить целую фразу?

Например, чтобы он находил начало ssid по тегу "ssid=", а заканчивал перед "pass=".

Решено.

Спасибо всем за помощь!

Я изучил оба варианта от @Majenko и @user7761803. Все они пригодились в различных частях кода.

Возможно, кто-то воспользуется библиотекой Regexp для разбора таких данных. Вот пример:

    #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) {
       // Получить SSID
       ssid = ms.GetCapture(regexp_var.buffer, 0);
       // Получить ПРОПУСК
       pass = ms.GetCapture(regexp_var.buffer, 1);
      }
    }

    void loop() {}

, 👍1

Обсуждение

Если вы работаете на ESP, в библиотеке https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer есть парсер arg() для строк запроса HTTP GET., @Dougie

@Dougie, спасибо!, @Delta


2 ответа


1

Обычным способом разбора таких сложных строк на любом языке является использование Регулярных выражений.

Обычно их довольно сложно использовать, но, к счастью, Ник Гаммон написал реализация регулярного выражения для Arduino.

,

Спасибо за помощь! Я разобрался с этой библиотекой., @Delta


3

Искомая функция strstr() требует двух строки и возвращает указатель на то место, где вторая строка появляется в первой (или NULL, если она не появляется).

Вы можете использовать это примерно так:

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) {
        // Одного или другого (или обоих) не хватает - что делать?
    } else {
        *r = '\0';  // Завершить последнюю строку

        // Если это действительно строка HTTP-запроса, мы не знаем
        // если первым будет ssid или pass
        if (p < q) {    // Завершить первую строку
            *(q - 1) = '\0';
        } else {
            *(p - 1) = '\0';
        }

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

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

Обратите внимание, однако, что ваша строка payload выглядит как строка HTTP-запроса.

Они определены таким образом, что они разделены по символам &, и если & должен появиться в одном из значений, он должен быть процентно закодирован (где & будет выглядеть как %26, после чего его нужно будет декодировать).

Однако это был не ваш вопрос...

,

Спасибо вам за помощь!, @Delta