Есть ли альтернатива 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() {}
@Delta, 👍1
Обсуждение2 ответа
Обычным способом разбора таких сложных строк на любом языке является использование Регулярных выражений.
Обычно их довольно сложно использовать, но, к счастью, Ник Гаммон написал реализация регулярного выражения для Arduino.
Спасибо за помощь! Я разобрался с этой библиотекой., @Delta
Искомая функция 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
- Чтение данных из Google Таблиц с помощью Nodemcu
- I2C связь между Arduino Uno и Nodemcu32-s (ESP32)
- Распознавание голоса Arduino
- PN532 не обнаруживает RFID-карту при подключении к ESP32 в режиме I2C, но отлично работает с Arduino Uno
- ESP32-Cam не отвечает и не может запрограммировать — истекло время ожидания заголовка пакета
- Связь Arduino Uno и ESP32 с использованием RS485
- Uno - ESP32 SoftwareSerial связь не работает
- Arduino uno R4 против платы разработчика ESP32
Если вы работаете на ESP, в библиотеке https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer есть парсер arg() для строк запроса HTTP GET., @Dougie
@Dougie, спасибо!, @Delta