Arduino (язык C) разбор строки с разделителем (ввод через последовательный интерфейс)

Arduino (язык C) разбор строки с разделителем (ввод через последовательный интерфейс)

Не нашел ответ здесь:/

Я хочу отправить на arduino через последовательный интерфейс (Serial.read()) простую строку из трех чисел, разделенных запятой. Эти три цифры могут быть в диапазоне 0-255.

Eg. 255,255,255 0,0,0 1,20,100 90,200,3

Что мне нужно сделать, так это разобрать эту строку, отправленную в arduino, на три целых числа (скажем, r, g и b).

Итак, когда я отправляю   100,50,30 arduino переведет его на

int r = 100
int g = 50
int b = 30

Я пробовал много кодов, но никто из них не работал. Основная проблема заключается в том, чтобы перевести строку (связку символов) в целое. Я понял, что, возможно, будет strtok_r для цели разделителя, но это о нем.

Спасибо за любые предложения:)

Ответ 1

Чтобы ответить на заданный вами вопрос, объекты String очень мощные, и они могут делать именно то, что вы просите. Если вы ограничиваете свои правила синтаксического анализа непосредственно со входа, ваш код становится менее гибким, менее многоразовым и слегка запутанным.

Строки имеют метод indexOf(), который позволяет вам искать индекс в массиве символов String определенного символа. Если символ не найден, метод должен возвращать -1. Второй параметр можно добавить к вызову функции, чтобы указать начальную точку для поиска. В вашем случае, поскольку ваши разделители являются запятыми, вы должны позвонить:

int commaIndex = myString.indexOf(',');
//  Search for the next comma just after the first
int secondCommaIndex = myString.indexOf(',', commaIndex + 1);

Затем вы можете использовать этот индекс для создания подстроки с использованием метода substring() класса String. Это возвращает новый String, начинающийся с определенного начального индекса, и заканчивается непосредственно перед вторым индексом (или конец файла, если ни один не указан). Таким образом, вы бы напечатали нечто похожее на:

String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex + 1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex + 1); // To the end of the string

Наконец, целые значения могут быть получены с использованием недокументированного метода класса String, toInt():

int r = firstValue.toInt();
int g = secondValue.toInt();
int b = thirdValue.toInt();

Более подробную информацию о объекте String и его различных методах можно найти в документации Arduino.

Ответ 2

Используйте sscanf;

const char *str = "1,20,100"; // assume this string is result read from serial
int r, g, b;

if (sscanf(str, "%d,%d,%d", &r, &g, &b) == 3) {
    // do something with r, g, b
}

Используйте мой код здесь, если вы хотите проанализировать поток строки ex: 255,255,255 0,0,0 1,20,100 90,200,3 Функция анализа для строки с разделителями-запятыми

Ответ 3

Я думаю, вы хотите сделать что-то подобное, чтобы читать данные:

String serialDataIn;
String data[3];
int counter;


int inbyte;

void setup(){
  Serial.begin(9600);
  counter = 0;
  serialDataIn = String("");
}

void loop()
{
    if(serial.available){
        inbyte = Serial.read();
        if(inbyte >= '0' & inbyte <= '9')
            serialDataIn += inbyte;
        if (inbyte == ','){  // Handle delimiter
            data[counter] = String(serialDataIn);
            serialDataIn = String("");
            counter = counter + 1;
        }
        if(inbyte ==  '\r'){  // end of line
                handle end of line a do something with data
        }        
    }
}

Затем используйте atoi(), чтобы преобразовать данные в целые числа и использовать их.

Ответ 4

Это здорово!

Последний комментарий о "thirdvalue = 0" является истинным из кода, приведенного в самом верхнем ответе @dsnettleton. Однако вместо использования "lastIndexOf (',');", код должен просто добавить "+1" в "secondCommaIndex", как @dsnettleton правильно сделал для commaIndex + 1 (отсутствует +1, вероятно, просто опечатка от парня).

Вот обновленный фрагмент кода

int commaIndex = myString.indexOf(',');
int secondCommaIndex = myString.indexOf(',', commaIndex+1);
String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex+1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex+1); //To the end of the string  

Пример)

Для myString = "1,2,3"

  • commaIndex = 1 (поиск по индексу 0, пятно, взятое символом 1, в положение первой запятой)
  • secondCommaIndex = 3 (поиск из индекса 2, место, взятое символом 2, в место следующей запятой)
  • firstValue читает из индекса 0-1 = "1"
  • secondValue читает из индекса 2-3 = "2"
  • thirdvalue читает из индекса 4-4 (последнее индексное пятно строки) = "3"

Примечание. Не путайте INDEX с ДЛИНОЙ строки. Длина строки равна 5. Так как String indexOf подсчитывается начиная с 0, последний индекс равен 4.

Причина, по которой просто

String thirdValue = myString.substring(secondCommaIndex);

возвращает 0, когда используется .toInt() - это потому, что thirdValue = ", 3", а не "3", который крепит toInt().

пс. жаль писать все инструкции, но как мех eng, даже мне иногда хотелось бы, чтобы кто-то замалчивал код для меня, особенно консультировался в течение последних 7 лет. Следите за потрясающей публикацией! Помогает людям, как я, много!

Ответ 5

Простейший, я думаю, использует parseInt() для выполнения этой задачи:

void loop(){
    if (Serial.available() > 0){
        int r = Serial.parseInt();
        int g = Serial.parseInt();
        int b = Serial.parseInt();
    }
}

делает трюк.

Ответ 6

Для n числа, разделенного строкой

int end;
while((end=str.indexOf(","))!=-1){
  String num = str.substring(0,end);
  str= asc.substring(end+1,str.length());
  Serial.println(num);  
}

Ответ 7

@cstrutton - отличное предложение об использовании 'indexOf'. это спасло мне массу времени для моего проекта. Тем не менее, один незначительный указатель,

Я заметил, что третье значение не отображалось (возвращалось как ZERO). Поиграв с ним немного и перейдя через документ в http://arduino.cc/en/Tutorial/StringIndexOf Я понял, я могу использовать lastIndexOf для последнего значения.

Вот две строки модификаций, которые обеспечивали правильное третье значение.

int lastCommaIndex = myString.lastIndexOf(',');

String thirdValue = myString.substring(lastCommaIndex+1); // To the end of the string

Ответ 8

    String myString = "dfsdfgsafhffgsdvbsdvdsvsdvsdsdfdfsdsff|date|recipt|weight|time|date|";

    // the setup routine runs once when you press reset:
    void setup() {                
        Serial.begin(9600); 
    }


// the loop routine runs over and over again forever:
void loop() {
 int Index1 = myString.indexOf('|');
int Index2 = myString.indexOf('|', Index1+1);
int Index3 = myString.indexOf('|', Index2+1);
int Index4 = myString.indexOf('|', Index3+1);
int Index5 = myString.indexOf('|', Index4+1);
int Index6 = myString.indexOf('|', Index5+1);
String secondValue = myString.substring(Index1+1, Index2);
String thirdValue = myString.substring(Index2+1, Index3);  
String fourthValue = myString.substring(Index3+1, Index4); 
String fifthValue = myString.substring(Index4+1, Index5); 
String firstValue = myString.substring(Index5+1, Index6); 
//Serial.println(Index1);
//
Serial.println(secondValue);
Serial.println(thirdValue);
Serial.println(fourthValue);
Serial.println(fifthValue);
Serial.println(firstValue);
delay(14000);
    }