Всем доброго времени суток. Возникла необходимость разпарсить строку. Если входящая строка = #r1_t=25; Код (C++): void setup() { Serial.begin(9600); } void loop() { String comands = "#r1_t=25;"; Serial.println(comands.substring(comands.indexOf("#r1_t=")+6,comands.indexOf(";"))); delay(500); } То выводит: С одной командой работает нормально, а вот с несколькими не работает. Если входящая строка = #r1_t=25; #r2_t=18; Код (C++): void setup() { Serial.begin(9600); } void loop() { String comands = "#r1_t=25; #r2_t=18;"; Serial.println(comands.substring(comands.indexOf("#r1_t=")+6,comands.indexOf(";"))); Serial.println(comands.substring(comands.indexOf("#r2_t=")+6,comands.indexOf(";"))); delay(500); } То выводит: А должно: При чем, входящая строка может быть и с другими командами, такими как #status; #temp; #all_off; и т.д Помогите, пожалуйста.
Сперва тебе надо разбить строку по разделителям (в твоём случае это ';'), потом уже каждую из этих подстрок разбирать. Ближайший аналог, который напрашивается на сравнение - элементы URI-запроса: /index.php?param1=a¶m2=qwerty¶m3=12345 То же самое, только разделитель '&'.
Выше сказано правильно, позволю себе немного дополнить. У тебя есть подстрока #r1_t=25, с помощью strtok отрезаешь (strtok(substring, "=")) часть строки, отвечающую за название команды (или переменной, не совсем понял, что там именно у тебя). Далее, ты можешь сравнить эту подстроку с уже известными тебе типами команд, чтобы понять, что именно тебе пришло. Потом ты еще раз используешь strtok(substring, NULL), и передвигаешь указатель на само значение, которое ты можешь конвертировать, например с помощью метода atoi. P.S. Не знаю, может ли strtok взаимодействовать с объектом класса String, но, что-то мне подсказывает, что может. В ином случае нужно будет переделать форму хранения строки под char массив
Сегодня решил переписать проект. Сравнивает, что пришло в терминал. Вот часть кода. Код (C++): #include <string.h> void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) check(Serial.readString()); } void check(String com) { int str_len = com.length() + 1; char str[str_len]; com.toCharArray(str,str_len); char* pch; pch = strtok (str," \n"); while (pch != NULL) { if((String)pch == "#r1_on;") { digitalWrite(13,1); } if((String)pch == "#r1_off;") { digitalWrite(13,0); } pch = strtok (NULL, " \n"); } } Как бы если в терминал пришла команда, то событие обрабатывается. Но, надо сравнивать команды типа этого, "#r1_t=" и т.д. Пробовал отсекать все что перед равно, строка Код (C++): strtok(s,tr"="); Но выводит только "#r1_t". А надо сравнивать "#r1_t=" Так как без равно могут быть и другое, например "#r1_t_off;" Как распарсить строку, с равно, если оно присутствует ?
Попробуйте парсить в ветвлениях. К примеру, порезали на подстроки. Теперь ищите знак "=". Если strtok вернул NULL, значит разделителя тут нет, и парсить нужно по другому. И приведите, пожалуйста, полный экземпляр подстроки с = и без, чтобы проще понимать было.
Как найти "=" ? В каждой подстроке, перебирать символы ? Если есть "=" то, парсить до "=" и полсе "=" до ";" ? Команд много, но для данной, "#r1_on;" "#r1_off;" "#r1_t=25;" 25 в этом случае, переменное значение. В место "#r1" может быть от 1 до 16.
Ну как вариант: Код (C++): if(strtok(str, "=")!=NULL){ strtok(str, "0 1 2 3 4 5 6 7 8 9"); int value=atoi(strtok(str, NULL)); UPD. Вообще, наверное не надо так делать. При первом вызове указатель изменится, и будет ошибка. Будет правильнее для проверки наличия в подстроке = использовать не strtok, а что-нибудь вроде этого: Код (C++): int index=0; while(index<sizeof(string)){ if(str[index]=="="){ strtok(str, "0 1 2 3 4 5 6 7 8 9"); int value=atoi(strtok(str, NULL)); break; } }
Я символ равно пытаюсь найти вот так: Код (C++): if(((String)pch).indexOf("=") != -1) { } Далее парсим до равно, Код (C++): if((String)(strtok(pch,"=")) == "#r1_t") { } Но вот проблема, Strok переписывает переменную pch, а не просто отбрасывает лишнее.
Ну, можно организовать так, что вам будет безразлично, сбрасывает он переменную, или нет. Объясните, чем именно вам это мешает? Или сохраняйте указатели в разные переменные
Алгоритм примерно такой: Если в подстроке присутствует знак = , то: Парсим все до равно. Если то что до равно, == команде, например "#r1_t" То, целую подстроку, в данном случае "#r1_t=25;" Парсим от '=' до ';' И получаем 25 Дальше обрабатываем действие.
Я не могу понять, почему strtok() переписывает переменную. Я объявил еще одну переменную. char* tmp = pch; Потом, сравниваем. ели да, то выводим pch. Код (C++): if((String)strtok(tmp,"=") == "#r1_t") { Serial.println(pch); } И выводит отпарсиную строку, хотя выводим переменную pch которая не должна меняться. А парсили строку tmp. Какой то бред в с++. На C# все намного легче.
Входная строка может меняться. В данном случае обрабатывается одна команда. Если входная строка "#r1_t=25;" если присутствует "#r1_t" то надо получить 25. Если входная строка "#r4_t=15;" если присутствует "#r4_t" то надо получить 15.
Если входная строка всегда из одной команды, то примерно так (считаем, что все переменные, в которые надо записывать значения, имеют тип int): Код (C++): typedef struct { int* var; // адрес переменной, в которую записывать значение const char* command; // команда, по приходу которой в переменную запишется нужное значение } t_link; int firstVariable; int secondVariable; t_link links[] = { {&firstVariable, "#r1_t"} , {&secondVariable, "#r4_t"} , {NULL, NULL} // заглушка }; void updateVariables(const char* incomingCommand) { byte cntr = 0; while(links[cntr].var) { if(strstr(incomingCommand,links[cntr].command) == incomingCommand) { const char* eqPtr = strstr (incomingCommand + strlen(links[cntr].command), "="); if(eqPtr) { eqPtr++; *(links[cntr].var) = atoi(eqPtr); } } cntr++; } } Писал навскидку, так что ошибки скорее всего есть. Но, надеюсь, принцип понятен: после прихода любой известной команды связанная с ней переменная должна быть обновлена.