ещё раз про strtok
- Войдите на сайт для отправки комментариев
Втр, 25/04/2017 - 10:29
Добрый день,
Помогите разобраться, почему не работает данный код:
Задача - разбирать полученную строку сначала на пары "переменная = значение", затем уже сами пары. Запрос может содержать любое количество пар.
else if(StrContains(HTTP_req, "GET /GTX?")) { //вид запроса GET /GTX?OUT_CircuPumpON=0&MHC_T_boil2=35&% HTTP/1.1
// sendXmlAnswer(cl);
int i = 1;
strtok(HTTP_req, "?"); // убираем GET /GTX
char* httpreq = strtok(NULL, "%");// выделяем строку от ? до %
strtok(httpreq, "&"); //Первая пара
while (httpreq != NULL){ //Крутим пока не закончатся пары
parsecom(i, httpreq);
httpreq = strtok(NULL, "&");
i++;
}
}
И функция разбора пар:
void parsecom(int number, char* data){
Serial.print(number);
Serial.print(" ");
Serial.print(data);Serial.print("\n");
char* Valuename = strtok(data, "=");
const char *lp_ptr = strtok(NULL, "=");
int value = atoi(lp_ptr);
for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
if (!strcmp(Valuename, valuename_strs[i])) {
values[i] = value;
Serial.print( valuename_strs[i]);
Serial.print(": ");
Serial.print(values[i]);
Serial.print("\n");
}
}
}
Если из функции убрать
char* Valuename = strtok(data, "=");
const char *lp_ptr = strtok(NULL, "=");
int value = atoi(lp_ptr);
То, на выходе в сериал мы получаем красивые пары с номером 1 OUT_CircuPumpON=0 ; 2 MHC_T_boil2=35 итд..
Но если начинаем разбирать пары внутри функции, то работает только первая пара и в цикл while программа даже не заходит, т.е. условие httpreq != NULL ложное. Из за чего это происходит? как strtok в функции влияет на выполнение когда основного кода?
могу показать как я работаю со строками запроса. без strtok
глоб переменные
функция чтения строки
void read_serial()// читаем все что пришло в сериал { String str_serial = ""; bool flag_read_complet = false; bool flag_komand_complet = false; while (Serial.available()) { //сохраняем входную строку в переменную str_serial int ch = Serial.read(); if(char(ch) == '<') {flag_read_complet = true;} else if(char(ch) == '>') {flag_read_complet = false;flag_komand_complet = true;} else if(flag_read_complet) {str_serial += char(ch);} delay(3); } //Serial.println(parseGetRequest(str_serial,_rele1)); Serial1.print("str_serial read="); Serial1.println(str_serial); if(flag_komand_complet) { for_major_rele1(parseGetRequest(str_serial,_rele1)); } str_serial = "";// входящая строка по сериал обработана (очистим) }дальше разбор идет вот в чем
вот что делают эти две функции
int parseGetRequest(String & str_inn, char* namePin)// примим входящую строку (String) и параметр (char), { //вернем целое положительное число (int) после = если такой параметр есть, если нет то вернет -1 int bedIndex = str_inn.indexOf("rele1"); if (bedIndex > -1) { String bedString = str_inn.substring(bedIndex + strlen(namePin) + 1); int bedRangeValue = bedString.toInt(); return bedRangeValue; } else { return -1; } }а эта функция меняет на новое значение если оно не совпадает со старым которое было
void for_major_rele1(int nev_val_pin)// { if ((nev_val_pin > -1)&&(nev_val_pin != int_rele1)) { digitalWrite(Pin_rele1, nev_val_pin); //изменим статус реле (включить реле) int_rele1 = nev_val_pin; } }я не утверждаю что это правельно...
и да тут есть кое что лишнее.
1. Не стоит запускать несколько цепочек strtok одновременно - они мешают друг другу. А у Вас они запускаются (одна внешняя, а другая внутри функции parsecom).
2. strtok гадит в строку с которой работает (помещает 0 на место найденного разделителя), это надо иметь в виду.
Я не понял. что там у Вас за фокусы вначале с ? и % - это Вы сами разберётесь. Я могу показать как разобрать строку типа
http://www.kaka.com/page.htm?a=123&kaka=mumu&b=1&p1=eshe_parameter
на имена и значения параметров.
Вот смотрите полный, работающий пример - там делов-то ...
template inline Print & operator << (Print &s, T n) { s.print(n); return s; } void setup() { Serial.begin(115200); char *request = "http://www.kaka.com/page.htm?a=123&kaka=mumu&b=1&p1=eshe_parameter"; char * pairPotinter = strtok(request, "?"); for (pairPotinter = strtok(NULL, "="); pairPotinter; pairPotinter = strtok(NULL, "=")) { const char * valuePointer = strtok(NULL, "&"); Serial << "name=" << pairPotinter << "; value=" << valuePointer << '\n'; } } void loop(void) {}Строку 5 вставщик кода переврал. Должна выглядеть как
char *request = "http://www.kaka.com/page.htm?a=123&kaka=mumu&b=1&p1=eshe_parameter";
Результат:
Большое спасибо!
Работает в таком виде:
else if(StrContains(HTTP_req, "GET /GTX?")) { //вид запроса GET /GTX?OUT_CircuPumpON=0&MHC_T_boil2=35 HTTP/1.1 char * pairPotinter = strtok(HTTP_req, "?"); for (pairPotinter = strtok(NULL, "="); pairPotinter; pairPotinter = strtok(NULL, "=")) { const char * valuePointer = strtok(NULL, "&"); int value = atoi(valuePointer); //перводим const char * valuePointer в int value for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными if (!strcmp(pairPotinter, valuename_strs[i])) { values[i] = value; Serial.print( valuename_strs[i]); Serial.print(": "); Serial.print(values[i]); Serial.print("\n"); } } } }У меня ругается при компиляции примера ЕвгенийП. Что не так?
Хрен его знает куда делся кусок из первой строки. Правильная первая строка вот такая
template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }В том посте подправить уже нельзя :(
Компилирует, но осталось:
/home/stable/Dropbox/Arduino/String-Serial/String-parse-D/String-parse-D.ino: In function 'void setup()':
Ну, Вы читать умеете? Во-первых это не ошибка, а предупреждение, а во-вторы, там же ясно написано, что автоматическое преобразование строковой константы в char * устарело.
Можете плюнуть, а можете после знака = написать (char *) - заткнётся.