Разбор строки

ustas
Offline
Зарегистрирован: 12.03.2012

Для одного своего проекта потребовалось разобрать строку.

Строка содержит следущие сущности:

- команда (строка, вообще говоря, произвольной длинны) - обязательный параметр

- идентификатор блока (строка, 3 символа) - обязательный параметр

- номер функции (число, пока от 0 до 9, но лучше - произвольное) - не обязательный параметр

- данные (число, пока от 0 до 9, но лучше - произвольное) - не обязательный параметр

Строку на передающей стороне собираю нормально... теперь проблема - разобрать ее нормально на принимающей стороне.

Пока заработал вот такой скетчик:

#include <string.h>

char unitID_in[10];
int devID_in;
char command_in[10];
char data_in[100];


void setup() {
  // открываем порт 
  Serial.begin(9600); 
}

void loop() {         

  int i=0;
  char buffer[100];

  //если есть данные - читаем
  if(Serial.available()){
    delay(100);

    //загоняем прочитанное в буфер
    while( Serial.available() && i< 99) {
      buffer[i++] = Serial.read();
    }
    //закрываем массив
    buffer[i++]='\0';
  }

  //если буфер наполнен
  if(i>0){  

    //разбераем его на части отделенные запятой
    sscanf(buffer, "%[^','],%[^','],%[^','],%s", &command_in, &unitID_in, &devID_in, &data_in);

  }

  if ((String)unitID_in == "001"){
    Serial.print("command: ");
    Serial.print(command_in);
    Serial.print("\n");
    Serial.print("unit: ");
    Serial.print(unitID_in);
    Serial.print("\n");
    Serial.print("dev: ");
    Serial.print(devID_in-48);
    Serial.print("\n");
    Serial.print("data: ");
    Serial.print(data_in);      
    Serial.print("\n");
    unitID_in [0] = '\0'; 
    command_in [0] = '\0';            
    devID_in = 0;            
    data_in [0] = '\0';            
  }
}

 

В этом скетче сначала все параметры входящие были строками (нормально работает, но нужны и целочисленные значения). Попробовал это сделать для параметра devID_in (см.строку 47 - какой-то некрасивый хак получился, особенно, когда данные для этого параметра отсутствуют).

Как строку разобрать лучше? Или, может, вообще как-то иначе работать со строкой?

Строка на передающей стороне получается примерно следующего вида: set,001,4,8

 

ustas
Offline
Зарегистрирован: 12.03.2012

Сам смешу - сам смеюсь :)

Разобрался с функцией sscanf.

пришлось переделать строку, которую дуина принимает (разделители должны быть пробелами (еще поддерживаются табуляторы)). Параллельно еще упростил свою систему (стало достаточно трех параметров в команде). 

Дальше все просто:

params = sscanf(buffer, "%s%s%d", &command, &unitID, &attr);
      

Дополнительно получено значение params - количество принятых параметров в строке.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Такие "умные" сишные функции - благо... пока хватает памяти. Потом наступает стадия оптимизация, приходится часто отказываться от "умных" функцый. 

ustas
Offline
Зарегистрирован: 12.03.2012

AlexFisher, а как быть в этом случае?

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Анализировать входящую строку посимвольно, преобразовывать в числа более "легкими" функциями, часто не библиотечными. Посмотрите тему про перевод принятой строки в число 

Вообще, общих советов нет. В ряде случаев победить библиотечную функцию вообще не удается.

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

А как получить параметры? тоесть обратиться например к строке 

Serial.print(data_in);

она не выводит ничего

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Поделитесь плиз, как правильно разбирать строки в порту, в том числе разделенные запятыми??

пример выше мне понравился, но почему он не силно правильный для ардуины?

Приведите примеры как выэто делаете, заране всем спасибо.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Что значит "в порту"? 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

в компорту....

 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

кстати, в тему ветки, пример из интернета:

http://bigbarrel.ru/arduino_serial_example/

как указать   вместо 1T - переод строки? тоесть у меня строка может быть разной длинны, и нужно указать что перед знаком перевода строки остановить считывание.

T1=Var.substring(Var.indexOf("T1")+2,Var.indexOf("1T"));

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Начните вот с этого поста и до конца темы смотрите, там ещё пример есть. Принцип у всех примеров один и тот же - любой разюорщик - конечный автомат. Примеры реализации там есть.