Как правильно сравнить строку типа string
- Войдите на сайт для отправки комментариев
Вс, 20/12/2015 - 18:57
Добрый день всем! Сразу скажу, что я не С++, а Delphi прогер, но жизнь заставляет изучать С++ и начал я сразу с языка для Ардуино... Открыл на днях коробочку с платкой и написал небольшой скетч. Суть в том, чтобы АрдуинаМега приняла данные с USB порта, а потом разобрала что нужно ей сделать. ВРоде все просто звучит, получил строковый код 1 - включил порт, получил 0 - отключил порт, но не могу заставить ее сравить строки )))
мой пример:
String inputString = "";
int ledpin=13;
boolean stringComplete = false;
void setup() {
Serial.begin(9600);
pinMode(ledpin,OUTPUT); // устанавливаем порт как выход
String inputString = "";
}
void loop() {
serialEvent();
if (stringComplete) // этот момент срабатывает четко... проверено.
{
Serial.println(inputString); // для моего контроля - смотрю что получила ардуино
if (inputString.substring(1)=="1") // вот тут загвоздка... не хочет никак переходить сюда... уже и просто inputString=="1" сравнивал, и никак
{
Serial.println("Led is ON");
digitalWrite(ledpin,HIGH);
}
inputString="";
stringComplete = false;
}
}
void serialEvent() {
while (Serial.available()) { // пока есть данные - делаем
char inChar = (char)Serial.read(); // читаем порт
inputString += inChar; // собираем в глобальную переменную полученные данные
if (inChar == '\n') { // если получили символ #10, то считаем что закончили прием
stringComplete = true;
}
}
}
На сколько мне позволяют знания Delphi применить к С++ я уже пробовал разное... чую, что тут все просто должно быть... а не выходит..
вот тебе рабочий код - адаптируй с DigiUSB на Serial
#include <DigiUSB.h> void setup() { pinMode(14, OUTPUT); // LED_01 digitalWrite(14, 1); pinMode(15, OUTPUT); // LED_02 digitalWrite(15, 1); DigiUSB.begin(); } void loop() { if (DigiUSB.available()) { // в USB что-то есть. char a = DigiUSB.read(); // считать символ из USB в переменную. static String b = ""; // объявление переменной строки. if (a != '\b') {b = b + a; } // дописать символ в конец строки, если это не символ клавиши Backspace. if (a == '\b') {b.remove(b.length() - 1);} // удалить последний символ строки, если получен символ клавиши Backspace. if (a == '\n') { // если получен символ клавиши Enter. // эхо строки. (необязательная часть кода, используется для отладки) if (DigiUSB.tx_remaining() > (b.length() + 1)) { // проверка места в буфере USB для строки длиной + 1 символ. DigiUSB.print(b); // печать в DigiUSB собранной строки. } // что-то делаем, после получения символа клавиши Enter. if (b == "LED_01 on\n") {digitalWrite(14, 0);} // зажечь светодиод, если принята строка ххх\n. if (b == "LED_01 of\n") {digitalWrite(14, 1);} // погасить светодиод, если принята строка ххх\n. if (b == "LED_02 on\n") {digitalWrite(15, 0);} // зажечь светодиод, если принята строка ххх\n. if (b == "LED_02 of\n") {digitalWrite(15, 1);} // погасить светодиод, если принята строка ххх\n. b = ""; // очистка строки. } } DigiUSB.delay(1); }Ну, сравнить-то их несложно, только зачем? Вам надо числа вводить? Так и вводите Serial.parseInt() - и введёт и к инту преобразует. Нафига Вам строки вообще?
Добрый день всем! Сразу скажу, что я не С++, а Delphi прогер, но жизнь заставляет изучать С++ и начал я сразу с языка для Ардуино... Открыл на днях коробочку с платкой и написал небольшой скетч. Суть в том, чтобы АрдуинаМега приняла данные с USB порта, а потом разобрала что нужно ей сделать. ВРоде все просто звучит, получил строковый код 1 - включил порт, получил 0 - отключил порт, но не могу заставить ее сравить строки )))
На сколько мне позволяют знания Delphi применить к С++ я уже пробовал разное... чую, что тут все просто должно быть... а не выходит..
попробуйте так
http://arduino.ru/Reference/StringCompareTo
Ну, сравнить-то их несложно, только зачем? Вам надо числа вводить? Так и вводите Serial.parseInt() - и введёт и к инту преобразует. Нафига Вам строки вообще?
Я чуток забегаю вперед, мне надо в дальнейшем посылать команду в виде кода функции и ее параметра в ардуино. Например 1х100 где 1 - это код фукции, а 100 ее параметр. К примеру задержка мерцания светодиода. Поэтому в чистом виде цифровой код сюда думаю не подойдет
if(b =="LED_01 of\n"Вот в чем похоже собака зарыта, \n ведь я не учел в конце строки.... А за код большое спасибо! То что надо для разбора данных полученных в порт по кускам...
if(b =="LED_01 on\n") - вот похоже в чем зарыта была собака... \n при сравнении строк не учел... А за пример большое спасибо! Удобно полученную строку разбивать по кускамтам не по кускам - строка собирается из отправленных символов, после получения \n (нажатия Enter) что-то делается - это не обязательно: что-то может исполнится и просто при получении LED_01 on
Ура господа!!! У меня все заработало как надо! ))) Вот мой рабочий пример:
int ledpin=13; // глобальная переменная со значением 13 boolean mig=false; String inputString = ""; // Строковая переменная String delfun = ""; boolean stringComplete = false; // Флажок на окончание приема данных int fdelay =500; // переменная для задержки мерцания void setup() { Serial.begin(9600); pinMode(ledpin,OUTPUT); // устанавливаем порт как выход String inputString = ""; String delfun = ""; } void loop() { serialEvent(); // переходим в процедуру опроса порта if (stringComplete) { // если мы получили данные Serial.println("Command: " + inputString); // для проверки того, что ардуино получил Serial.println("Function: " + delfun); if (inputString=="1") { Serial.println("Led is ON"); digitalWrite(ledpin,HIGH); mig=false; } if (inputString=="0") { Serial.println("Led is OFF"); digitalWrite(ledpin,LOW); mig=false; } if (inputString=="2") { Serial.println("Led is Flash"); mig=true; } if (inputString=="clr\n") { Serial.flush(); Serial.println("Port is clear"); } delfun=""; inputString=""; stringComplete = false; fdelint=0; } if (mig==true) { digitalWrite(ledpin,HIGH); delay(fdelay); digitalWrite(ledpin,LOW); delay(fdelay); } } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); // получаем данные с порта inputString += inChar; // собираем всю строку if (inChar == '\n') // если наткнулись на перевод коретки { for (int i=1; i<=inputString.length()-1; i++ ) // собираем строку после первого символа, т.е читаем значение переданного параметра { delfun = delfun + inputString.charAt(i); // собираем наш полученный параметр } if (inputString != "clr\n") // исключение команды очистки порта { inputString=inputString.charAt(0); // берем наш первый символ, который определяет функцию fdelay = atoi(delfun.c_str()); // преобразуем наш параметр в число } stringComplete = true; } } }Спасибо Вам большое!
Спасибо за пример, но в моём случае не работает.
Задача принять строку по UART и сравнить с константой.
Как и вы использовал модифицированный пример SerialEvent из https://www.arduino.cc/en/Tutorial/SerialEvent
String inputString = ""; // a String to hold incoming data boolean stringComplete = false; // whether the string is complete void setup() { Serial.begin(19200); inputString.reserve(200); } void loop() { if (stringComplete) { Serial.println(inputString); if (inputString.equals("Hello")) { Serial.println("WIN1!"); } if (inputString == ("Hello")) { Serial.println("WIN2!"); } inputString = ""; stringComplete = false; } } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); if (inChar != '\n') { inputString += inChar; } if (inChar == '\n') { stringComplete = true; } } }String inputString = ""; // Строковая переменная String delfun = ""; boolean stringComplete = false; // Флажок на окончание приема данных void setup() { Serial.begin(19200); String inputString = ""; String delfun = ""; } void loop() { serialEvent(); // переходим в процедуру опроса порта if (stringComplete) { // если мы получили данные Serial.println("Input: " + delfun); // для проверки того, что ардуино получил if (delfun=="Hello") { Serial.println("WIN"); } if (inputString=="clr\n") { Serial.flush(); Serial.println("Port is clear"); } delfun=""; inputString=""; stringComplete = false; } } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); // получаем данные с порта inputString += inChar; // собираем всю строку if (inChar == '\n') // если наткнулись на перевод коретки { for (int i=0; i<=inputString.length()-1; i++ ) // собираем строку { delfun = delfun + inputString.charAt(i); // собираем наш полученный параметр } stringComplete = true; } } }Прошу помощи в решении этой простой для вас задачи.
В первом случае все вроде верно, только скобки вокруг сравниваемой строки (строка 15) - я бы убрал. Не знаю, мешают они или нет, но так писать не принято.
Почему не выдается WIN? Думаю. в конце строки еще есть спецсимволы. зависящие от режима терминала - а вы их не учитываете
Спасибо за ответ.
Я тоже подумал о спец. символах, но и это не сработало:
String inputString = ""; // a String to hold incoming data boolean stringComplete = false; // whether the string is complete void setup() { Serial.begin(19200); inputString.reserve(200); } void loop() { if (stringComplete) { Serial.println(inputString); if (inputString.equals("Hello")) { Serial.println("WIN1!"); } if (inputString == "Hello") { Serial.println("WIN2!"); } if (inputString.substring(0,4) == "Hello") { Serial.println("WIN3!"); } inputString = ""; stringComplete = false; } } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); if (inChar != '\n') { inputString += inChar; } if (inChar == '\n') { stringComplete = true; } } }Код Клапауций 321 тоже не работает(
Какая-то причина для опытных программистов ясная, а мне не понятная.
Почему это не работает:
void setup() { Serial.begin(19200); } void loop() { if (Serial.available()) { // в Serial что-то есть. char a = (char)Serial.read(); // считать символ из UART в переменную. static String b = ""; // объявление переменной строки. if (a != '\b') {b = b + a;} // дописать символ в конец строки, если это не символ клавиши Backspace. if (a == '\b') { b.remove(b.length() - 1);} // удалить последний символ строки, если получен символ клавиши Backspace. if (a == '\n') { // если получен символ клавиши Enter. // эхо строки. (необязательная часть кода, используется для отладки) if (Serial.availableForWrite() > (b.length() + 1)) { // проверка места в буфере Serial для строки длиной + 1 символ. Serial.print(b); // печать в DigiUSB собранной строки. } // что-то делаем, после получения символа клавиши Enter. if (b == "Hello\n") {Serial.print("Klapauciy 321 WIN!");} // если принята строка ххх\n. b = ""; // очистка строки. } } }Pacient, напечатать посимвольно получившуюся строку b религия не позволила?
Хрустальный Шар подсказывает, что если Вы в 20-ой строке замените "Hello\n" на "Hello\r\n", то Вам будет много счастья. Но так нельзя работать. При любых непонятках, надо сначала
вызывать скорую, а уж потом выкладывать в инстаграммпечатать переменные и смотреть на них, а только потом, если непонятки остались, постить вопросы.Кстати, на обычных указателях char * эта задача решается существенно короче по строкам кода и неизмеримо эффективнее по времени и памяти.
Спасибо за ответ.
Я тоже подумал о спец. символах, но и это не сработало:
if (inputString.substring(0,4) == "Hello") { Serial.println("WIN3!");похоже, кто-то просто не умеет считать. Сколько букв в слове "Hello"? Четыре? :)
В посте №11 уже нет этой четвёрки, но не помогло :)
В посте №11 уже нет этой четвёрки, но не помогло :)
Зато код из #10 заработал бы :) и автор ушел бы довольный....
Хрустальный Шар подсказывает, что если Вы в 20-ой строке замените "Hello\n" на "Hello\r\n", то Вам будет много счастья.
откуда у него там \r берётся, если он его не отсылает по сериалу?
откуда у него там \r берётся, если он его не отсылает по сериалу?
Там в окне монитора внизу можно установить что отсылать: ничего, \n или \r\n. Что там установлено у ТС одному Богу ведомо, но раз не работает, то скорее всего проблема в том, что \r\n стоит, а он голого \n ожидает.
Первый код, из сообщения номер 8 работает и печатает и Вин1 и Вин2.
Кончайте бредить!
1. в "Мониторе порта" нужно поставить КОНЕЦ СТРОКИ - NL (это в нижней строке справа). Проверка-то идет на '\n'.
2. на arduino.cc АГЛИЦКИМ _ПО_БЕЛОМУ написано, что это самый сериа-евент - работает только на УНО и НАНО (на меге - с номерами).
Так вот на Нанке - код от вопрошающего запускается и работает сразу и без размышлений.
Там в окне монитора внизу можно установить что отсылать: ничего, \n или \r\n. Что там установлено у ТС одному Богу ведомо, но раз не работает, то скорее всего проблема в том, что \r\n стоит, а он голого \n ожидает.
нда. кароче, всем потерпевшим от сериал монитора - код #1 подразумевает, что по сериалу летят символы введённые клавой, а не отправленные каким-то сериал-понитором и прочей шнягой калечащей инфу.
Первый код, из сообщения номер 8 работает и печатает и Вин1 и Вин2.
Кончайте бредить!
1. в "Мониторе порта" нужно поставить КОНЕЦ СТРОКИ - NL (это в нижней строке справа). Проверка-то идет на '\n'.
2. на arduino.cc АГЛИЦКИМ _ПО_БЕЛОМУ написано, что это самый сериа-евент - работает только на УНО и НАНО (на меге - с номерами).
Так вот на Нанке - код от вопрошающего запускается и работает сразу и без размышлений.
Всё верно. Работает без CR (возврат каретки).
Вопрос закрыт, спасибо!
Ну, слава Богу! Человеческий разум в очередной раз восторжествовал! :)
if (Serial.available()) { char in = Serial.read();// считать символ из serial в переменную. static String b = ""; // объявление переменной строки. b = b + in; // дописать символ в конец строки if (b == "Led1 On Led2 Off") { Led1Enable(); b = ""; } if (b == "Led2 On Led1 Off") { Led2Enable(); b = ""; } }Друзья! я кажется нашел решение! Представляю на Ваш суд:
String inputString = ""; boolean stringComplete = false; void setup() { Serial.begin(9600); String inputString = ""; } void loop() { while (Serial.available()) { // пока есть данные - делаем char inChar = (char)Serial.read(); // читаем порт if (inChar == '\n') // если получили символ #10, то считаем что закончили прием { inChar = 0; stringComplete = true; } inputString += inChar; // собираем в глобальную переменную полученные данные } if (stringComplete){ Serial.println(inputString); if(inputString == "hello"){ Serial.println("Good Work!"); } inputString=""; } stringComplete = false; }Это работает если в сериал-мониторе в правом нижнем углу выставлено NL(Новая строка)!
Друзья! я кажется нашел решение! Представляю на Ваш суд:
Это что за решение? Какой задачи? В смысле, что делать-то хотели?
Думаю, что это ответ на главный вопрос жизни, вселенной и всего такого.
у меня была таже проблема и задача, что и у автора - на UART приходят команды, в мооем случае типа: Е02, Y1, AE, HS0 и т.д. И все не работало как нужно, выше все описано. У меня не работало сравнение строк, и Good Work никак не приходило в ответ, а все из-за гребаного \n в конце любой комбинации символов переданных по UART. Под Good Work естественно подразумевается выполнение полезной работы.
У меня не работало сравнение строк, и Good Work никак не приходило в ответ, а все из-за гребаного \n в конце
Понятно, т.е. на самом деле, у Вас правильно работало сравнение строк, когда они были не равны, программа и говорила, что они не равны. А понять почему они не равны и сделать их равными Вы не могли. ну, так и говорите.
Думаю, что это ответ на главный вопрос жизни, вселенной и всего такого.
Ты забыл? Там "42"! ;)))
Добрый день!
Уже который день пытаюсь подружить ардуино, датчик давления и реле через последовательный порт. Давление воды с датчика приходит без проблем и показывается на мониторе порта. А вот управлять нагрузкой (реле для закрывания / открывания линии воды) пока получается с трудом. Единственное, чего я смог пока добиться - управление нагрузкой (светодиодом, а впоследствии транзистором и реле) через команды 0 и 1. Т. е. в случае 0 13 диод не горит, а при 1 диод загорается. По моей задумке, в проекте реле будет не одно, а несколько. И как ими управлять? Я думал сделать на открытие / закрытие каждого клапана команды от 0 до 13. Но вот незадача - ардуино через порт принимает число 10 не как десять, а как один ноль. И поэтому сначала зажигает диод, а по прошествии времени задержки его тушит. Если послать на порт 10101010, то микросхема мигает соответствующее количество раз. Я думал, что было бы идеально высылать команду LED1ON для зажигания диода №1 и команду типа LED4OFF для гашения диода 4. Но как ни бился - не получается. Помогите, пожалуйста!
/* Программа для прошивки ардуино под снятие данных с датчика давления и управлением реле */ // y = k * x + b // Давление (Па) = k * Напряжение (В) + b const float b = 0.586, k = 0.000009; String val; float U, P; void setup() { Serial.begin(115200); // open serial port, set the baud rate to 9600 bps Serial.println("/** Измерение давления датчиком **/"); pinMode (13,OUTPUT); } void loop() { //Connect sensor to Analog 0 U = analogRead(0) * 5.00 / 1024; // Считывание напряжение (0-5 В) через аналоговый вход P = 106939 * U - 61062 + 492; // Расчёт избыточного давления в Па Serial.print(" Напряжение:"); Serial.print(U, 3); Serial.println(" В"); Serial.print(" Избыточное давление:"); Serial.print(P, 0); Serial.println(" Па"); Serial.println(); val=Serial.readString(); if(val=='1on') {digitalWrite(13,HIGH);} else if (val=='1off') {digitalWrite (13,LOW);} else (val==val); delay(500); }'1on' - это не строка, строка - это "1on".
Спасибо! Добавил ещё символ Enter и всё заработало!
/* Программа для прошивки ардуино под снятие данных с датчика давления */ // y = k * x + b // Давление (Па) = k * Напряжение (В) + b const float b = 0.586, k = 0.000009; String val; float U, P; void setup() { Serial.begin(9600); // open serial port, set the baud rate to 9600 bps Serial.println("/** Измерение давления датчиком **/"); pinMode (13,OUTPUT); } void loop() { //Connect sensor to Analog 0 U = analogRead(0) * 5.00 / 1024; // Считывание напряжение (0-5 В) через аналоговый вход P = 106939 * U - 61062 + 492; // Расчёт избыточного давления в Па Serial.print(" Напряжение:"); Serial.print(U, 3); Serial.println(" В"); Serial.print(" Избыточное давление:"); Serial.print(P, 0); Serial.println(" Па"); Serial.println(); val=Serial.readString(); if(val=="1on\n") {digitalWrite(13,HIGH);} else if (val=="1off\n") {digitalWrite (13,LOW);} else (val==val);