Работа с текстови низове на arduino. Увиване на дълги линии. Функции и методи на клас String


Текст на низ = "Temp:" + tempC + "C";

Уви, това не работи в C. V в такъв случайсъобщението може да бъде отпечатано с множество изрази за печат, както е показано по-долу:

lcd.print ("Temp:"); lcd.print (tempC); lcd.print ("C");

Този подход елиминира необходимостта от задкулисно копиране на данни по време на конкатенация на низове (конкатенация), какъвто е случаят в други съвременни езици.

Подобен подход с множество изходни инструкции може да се използва при работа с монитор сериен порти инструкции за Serial.print. V подобни случаипоследният на ред обикновено е командата println, която добавя подаване на ред в края.

Форматиране на низове с с помощта на sprintf

Стандартна библиотека низови функцииза езика C (да не се бърка с библиотеката на Arduino String Object, която е разгледана в следващия раздел) включва много удобна функция sprintf за форматиране на символни масиви. Той вмъква променливи стойности в низа на шаблона, както е показано в следния пример:

спринт (ред 1, "Temp:% d C", tempC);

Масивът от символи line1 е низов буфер, съдържащ форматиран текст. Както е посочено в примера, той има капацитет от 17 знака, включително допълнителен нулев знак в края. Избрах името line1, защото ще ви покажа как да генерирате съдържанието. горна линияза течнокристален дисплей с два реда по 16 знака всеки.

Първият параметър на командата sprintf е масив от знаци, в който трябва да се запише резултатът. Следващият аргумент е форматен низ, съдържащ микса обикновен тексткато Temp : и команди за форматиране като% d. В този случай % d означава десетично число със знак. Останалите параметри ще бъдат заместени във форматиращия низ в реда, в който се появяват на мястото на командите за форматиране.

За да се покаже времето във втория ред на дисплея с течни кристали, то може да се формира от индивидуални стойности на часове, минути и секунди, както е показано по-долу:

sprintf (ред 2, "Време:% 2d:% 02d:% 02d", h, m, s);

Ако се опитате да отпечатате линия 2 на серийния монитор или LCD екран, ще видите текста

Sprintf не само замества числата правилните места, но също така е добавена водеща нула преди числото 5. В примера между знаците: има команди за форматиране за трите времеви компонента. Часовникът съответства на командата% 2d, която извежда двуцифрено десетично число. Командите за форматиране за минути и секунди са малко по-различни (% 02d). Тези команди също извеждат двуцифрено число десетични числано добавете водеща нула, ако е необходимо.

Имайте предвид обаче, че тази техника е за стойности от тип int... За съжаление, разработчиците на Arduino не го внедриха стандартна библиотекаПоддръжка на C за други типове, като например float.

Определяне на дължината на низ

Тъй като низовете, съхранявани в символни масиви, често са по-къси от самите масиви, библиотеката предоставя удобна функция, наречена strlen. Тази функция отчита броя на знаците в масива, предхождащ нулевия знак, който маркира края на низа.

Функцията приема масив от знаци в единствения си параметър и връща размера на низа (с изключение на празния знак), съхранен в него, например командата

ще върне числото 3.

Библиотека с обекти на Arduino String

V Arduino IDEот версия 019, пусната преди няколко години, е включена библиотеката String, която е по-разбираема и удобна за разработчиците, използващи Java, Ruby, Python и други езици, където е разрешена конкатенация на низове прост оператор+. Тази библиотека предлага и множество помощни функции за работа с низове.

Разбира се, тази библиотекадобавя няколко килобайта код към скицата. В допълнение, той използва механизъм за динамично разпределение на паметта с всички съпътстващи проблеми като изчерпване на паметта. Затова помислете внимателно, преди да решите да го използвате. Много потребители на Arduino предпочитат да използват обикновени символни масиви.

Тази библиотека е изненадващо лесна за използване и ако някога ви се е налагало да работите със низове в Java, библиотеката на Arduino String Object ще ви накара да се почувствате като у дома си.

Създаване на низове

Можете да създадете низ от масив от елементи от тип charкакто и от int или float стойност, както е показано в следния пример:

String message = "Temp:";

String temp = String (123);

Конкатениране на низове

Низовете от тип String могат да бъдат свързани помежду си и с данни от други типове с помощта на оператора +. Опитайте да добавите следния код към функцията за настройка на вашата празна скица:

Serial.begin (9600);

String message = "Temp:";

String temp = String (123);

Serial.println (съобщение + temp + "C");

Имайте предвид, че последната добавена стойност към низа всъщност е масив от знаци. Ако първият елемент в последователността от стойности между + операторите е низ, останалите елементи автоматично ще бъдат преобразувани в низове, преди да бъдат свързани.

Други низови функции

Таблица 6.1 изброява още няколко удобни функцииот библиотеката String. Пълен списък налични функцииможете да намерите на http://arduino.cc/en/Reference/StringObject.

Таблица 6.1.някои полезни функциив библиотеката String

Функция

Пример

Описание

char ch = Низ ("abc")

Променливата ch ще получи стойността "a"

Низ s = "abc";

Премахнете интервалите от двете страни на групата символи abc. Променливата s ще получи стойността "abc"

Низ s = "123";

int x = s.toInt ();

Преобразува низовото представяне на число в int или long

Низ s = "abcdefg";

Низ s2 = s.подниз (1, 3);

Връща част от оригиналния низ. Променливата s2 ще получи стойността "bc". Предават се параметрите: индексът на първия знак от фрагмента и индексът на следващия знак последен знакфрагмент

Низ s = "abcdefg";

s.замени ("de", "DE");

Заменя всички поява на "de" в низа с "DE". Променливата s2 ще получи стойността "abcDEfg"

Използване на EEPROM

Съдържанието на всички променливи, използвани в Ардуино скица, се губи, когато захранването се изключи или когато се извърши нулиране. За да съхранят стойностите, те трябва да бъдат записани байт по байт в EEPROM паметта. V Arduino UnoНаличен е 1KB EEPROM.

ЗАБЕЛЕЖКА

Това не се отнася за Arduino платка Due, който няма EEPROM. В този модел данните трябва да се записват на microSD карта.

За да четете и записвате данни в EEPROM, трябва да използвате библиотеката, включена в Arduino IDE. Следният пример демонстрира как да запишете един байт в EEPROM, в този случай операцията се извършва във функцията за настройка:

#включи

байт стойностToSave = 123

EEPROM.write (0, valueToSave);

Първият аргумент на функцията за запис е EEPROM адресът, където трябва да се запише байтът на данните, а вторият е стойността, която да се запише на този адрес.

Текстовите низове могат да бъдат декларирани по два начина: можете да използвате типа данни String, който е включен в ядрото от версия 0019; или декларирайте низа като null-терминиран char масив. Тази страница описва втория метод. За още подробна информацияза String обект, който предоставя повече функционалност при по-висока цена на паметта, вижте страницата String Object.

Примери за

По-долу са дадени примери за правилни декларации на низове.

Char Str1; char Str2 = ("a", "r", "d", "u", "i", "n", "o"); char Str3 = ("a", "r", "d", "u", "i", "n", "o", "\ 0"); char Str4 = "arduino"; char Str5 = "arduino"; char Str6 = "arduino";

char Str1 [15];

char Str2 [8] = ("a", "r", "d", "u", "i", "n", "o");

char Str3 [8] = ("a", "r", "d", "u", "i", "n", "o", "\ 0");

char Str4 = "arduino";

char Str5 [8] = "arduino";

char Str6 [15] = "arduino";

Разрешени операции при деклариране на низове

  • Декларирайте символен масив, без да го инициализирате (Str1)
  • Декларирайте символен масив с един излишен елемент, компилаторът ще добави самия нулев символ (Str2)
  • Добавете нулев знак изрично (Str3)
  • Инициализирайте масива, използвайки низова константа в кавички; компилаторът ще създаде масив необходимия размерс нулев край (Str4)
  • Инициализирайте масив с помощта на низова константа, като изрично укажете неговия размер (Str5)
  • Инициализирайте масив с голям размер, оставяйки място за по-дълги низове (Str6)

Нулев завършващ символ

Обикновено всички низове са завършвани с нула (ASCII код 0), което позволява на функции (като Serial.print ()) да определят дължината на низа. Без този знак те ще продължат да четат последователно байтове памет, които всъщност вече няма да са част от низа.

По принцип това означава, че вашият низ трябва да е с 1 знак по-дълъг от текста, който искате да съхраните в него. Ето защо Str2 и Str5 трябва да са дълги 8 знака, въпреки факта, че думата "arduino" е само 7 - последната позиция автоматично се запълва с нулев знак. Размерът на Str4 автоматично ще стане 8 - един знак е необходим за крайна нула. В ред Str3 ние сами сме посочили нулевия символ (означен с '\ 0').

Имайте предвид, че по принцип можете да декларирате низ без завършващ нулев символ (например, ако зададете дължината на Str2 на 7, а не на 8). Това обаче ще направи повечето от низовите функции неработоспособни, така че не трябва да правите това умишлено. Тази грешка може да е причината странно поведениеили появата на символи на трети страни при работа с низове.

Единични или двойни кавички?

Низовете винаги се декларират in двойни кавички(„Abc“), а знаците винаги се декларират в единични кавички („A“).

Увиване на дълги линии

Дългите редове могат да бъдат увити по следния начин:

char myString = "Това е първият ред" "това е вторият ред" "и така";

char myString = "Това е първият ред"

"това е втория ред"

"и така нататък";

Масиви от низове

При работа с големи обемитекст (например в проекти, които работят с LCD екран) често е удобно да се използват масиви от низове. Тъй като низовете сами по себе си са масиви, това всъщност е пример за двуизмерен масив.

В следващата програма звездичката след типа данни char "char *" показва, че променливата е масив от "указатели". Всички имена на масиви всъщност са указатели, така че звездичката е необходима за създаване на масив от масиви. Указателите в C са едно от по-трудните неща за начинаещи, но в този случай дълбоко разбиране на указателите за тях ефективно използванеизобщо не се изисква.

Пример

char * myStrings = ("Това е низ 1", "Това е низ 2", "Това е низ 3", "Това е низ 4", "Това е низ 5", "Това е низ 6"); void setup () (Serial.begin (9600);) void loop () (за (int i = 0; i< 6; i++){ Serial.println(myStrings[i]); delay(500); } }

char * myStrings = ("Това е низ 1", "Това е низ 2", "Това е низ 3",

Стигнах до програмирането като цяло и Ардуино програмиранев частност, пълна нула, преди около два месеца. Сега, в хода на сегашната си дейност, почувствах нужда да овладея обработката на редове на arduino. Обичайното пътуване до Google за информация не зарадва статията, където всичко е написано по прост и разбираем начин за манекени. И затова съм тук, за да говоря за това как е реализиран синтактичен анализ на линиите от серийния порт и кои от тях са се срещали по пътя. подводни скали... Питам заинтересованите под кат.

Така. Ето примерен алгоритъм, който следвах:

  1. Отиваме на arduino.ru и търсим всичко свързано със символи в колоната тип.
  2. Решаваме каква форма на представяне ще използваме (спрях се на класа String, защото имах неприятен опит с mash масиви).
  3. Ние трескаво се опитваме да напишем нашата функция с предпочитания и професии
  4. Търсим клас.
  5. Търсим необходимите оператори.
  6. Ние пишем!
И алгоритъмът на основното тяло на програмата е прост:
  1. Проверяваме циклично дали буферът съдържа com портчетим байт, ако има такъв, четим.
  2. Ако полученият байт е символ за подаване на ред ("\ n"), тогава ние извикваме функцията за самонаписан синтактичен анализ, ако не, тогава добавяме получения байт към създадения променлива катониз.
  3. Накрая анализирайте низа.

    Всъщност, тъй като практическа употребатогава синтактичният анализ на низовете е изключен тази функцияе само демонстративно, сравнявайки получения низ с константен низ, който вече е записан в паметта. И така, използвайки оператора equals, ние сравняваме получения низ с написания и ако операторът върне true, излизаме от функцията манипулатор, ако не, сравняваме със следващия. Ако низовете са еквивалентни, тогава отново излезте от функцията манипулатор, връщайки резултата. Е, дори ако това условие не работи, ние пак ще излезем от функцията и ще кажем, че низът не е правилен.

  4. В зависимост от приетия резултат се използва кутия за превключвателизберете този, който искате.
  5. Обнуляваме получения низ, за ​​да можем да започнем да го събираме отново по-късно.

И накрая, ето кода:

#define led 13 String input_string = ""; const String Led_off = "изключете светодиода"; const String Led_on = "включете светодиода"; bool led_running; void setup () (Serial.begin (9600);) void loop () (докато (Serial.available ()> 0) (char c = Serial.read (); if (c == "\ n") (Serial .print ("Input_string is:"); Serial.println (input_string); превключвател (синтактичен анализ (input_string, Led_off, Led_on)) (случай 10: led_running = false; Serial.println ("Изключването е извършено"); break; случай 11: led_running = true; Serial.println ("Включването е извършено"); прекъсване; случай 0: Serial.println ("невалиден низ"); break;) input_string = ""; digitalWrite (LED, led_running);) else (input_string + = c;))) байт синтактичен (String input_string, const String Led_off, const String Led_on) (if (input_string.equals (Led_off) == true) (връщане 10;) else if (input_string.equals (Led_on) ) == true) (връщане 11;) иначе връщане на 0;)


Така че, не разбирам, какъв бизнес? Защо светодиодът не свети? О, да, как забравих това, трябва да добавите към настройката void:

PinMode (светодиод, OUTPUT);

P.S.: Важно е да настроите монитора на com порта в Arduino IDE на " Нова линия“, Защото във всеки друг, изпратеният низ няма да бъде последван от неговия завършващ знак "\ n".

P.P.S.: Няма да участвам в холивара относно факта, че ардуино е необходим, не съм направил нищо лошо, докато изучавам основите на програмирането и алгоритмизацията.

P.P.P.S.: Ако статията бъде приета адекватно, ще напиша следната за случилото се с мен с подобряването на функционалността на функцията за парсинг. Е, с Бог! ...

Стигнах до програмирането като цяло и програмирането на Arduino в частност, напълно нула, преди около два месеца. Сега, в хода на сегашната си дейност, почувствах нужда да овладея обработката на редове на arduino. Обичайното пътуване до Google за информация не зарадва статията, където всичко е написано по прост и разбираем начин за манекени. И затова съм тук, за да говоря за това как е реализиран синтактичен анализ на низове от серийния порт и какви клопки се срещнаха по пътя. Питам заинтересованите под кат.

Така. Ето примерен алгоритъм, който следвах:

  1. Отиваме на arduino.ru и търсим всичко свързано със символи в колоната тип.
  2. Решаваме каква форма на представяне ще използваме (спрях се на класа String, защото имах неприятен опит с mash масиви).
  3. Ние трескаво се опитваме да напишем нашата функция с предпочитания и професии
  4. Търсим клас.
  5. Търсим необходимите оператори.
  6. Ние пишем!

И алгоритъмът на основното тяло на програмата е прост:

  1. Проверяваме циклично дали има четим байт в буфера на com порта и ако е така, четем го.
  2. Ако полученият байт е символ за нов ред ("n"), тогава ние извикваме функцията за синтактичен анализ, ако не, тогава добавяме получения байт към създадената променлива от типа String.
  3. Накрая анализирайте низа.

    Всъщност, тъй като Практическото използване на синтактични низове не работи за мен, тогава тази функция има само демонстративен характер, сравнявайки получения низ с константен низ, който вече е записан в паметта. И така, използвайки оператора equals, ние сравняваме получения низ с написания и ако операторът върне true, излизаме от функцията манипулатор, ако не, сравняваме със следващия. Ако низовете са еквивалентни, тогава отново излезте от функцията манипулатор, връщайки резултата. Е, дори ако това условие не работи, ние пак ще излезем от функцията и ще кажем, че низът не е правилен.

  4. В зависимост от приетия резултат с с помощта на превключвателслучай, изберете този, който искате.
  5. Обнуляваме получения низ, за ​​да можем да започнем да го събираме отново по-късно.

И накрая, ето кода:

#define led 13 String input_string = ""; const String Led_off = "изключете светодиода"; const String Led_on = "включете светодиода"; bool led_running; void setup () (Serial.begin (9600);) void loop () (докато (Serial.available ()> 0) (char c = Serial.read (); if (c == "n") (Serial. print ("Input_string is:"); Serial.println (input_string); превключвател (разбиране (input_string, Led_off, Led_on)) (случай 10: led_running = false; Serial.println ("Изключването е извършено"); прекъсване; случай 11: led_running = true; Serial.println ("Включването е извършено"); прекъсване; случай 0: Serial.println ("невалиден низ"); break;) input_string = ""; digitalWrite (LED, led_running);) друго (input_string + = c;))) байт синтактичен (String input_string, const String Led_off, const String Led_on) (if (input_string.equals (Led_off) == true) (връщане 10;) else if (input_string.equals (Led_on) == вярно) (връщане 11;) иначе връщане на 0;)

Така че, не разбирам, какъв бизнес? Защо светодиодът не свети? О, да, как забравих това, трябва да добавите към настройката void:

PinMode (светодиод, OUTPUT);

P.S.: Важно е да настроите монитора на com порта в Arduino IDE на режим "Нова линия", т.к. в противен случай изпратеният низ няма да бъде последван от неговия терминатор "n".

P.P.S.: Няма да участвам в холивара относно факта, че ардуино е необходим, не съм направил нищо лошо, докато изучавам основите на програмирането и алгоритмизацията.

P.P.P.S.: Ако статията бъде приета адекватно, ще напиша следната за случилото се с мен с подобряването на функционалността на функцията за парсинг. Е, с Бог! ...

Текстовите низове могат да бъдат декларирани по два начина: можете да използвате типа данни String, който е включен в ядрото от версия 0019; или декларирайте низа като null-терминиран char масив. Тази страница описва втория метод. За повече информация относно String обект, който предоставя повече функционалност с цената на повече памет, вижте страницата String Object.

Примери за

По-долу са дадени примери за правилни декларации на низове.

Char Str1; char Str2 = ("a", "r", "d", "u", "i", "n", "o"); char Str3 = ("a", "r", "d", "u", "i", "n", "o", "char Str1; char Str2 = (" a "," r "," d "," u "," i "," n "," o "); char Str3 = (" a "," r "," d "," u "," i "," n "," o " , "\ 0"); char Str4 = "arduino"; char Str5 = "arduino"; char Str6 = "arduino"; "); char Str4 = "arduino"; char Str5 = "arduino"; char Str6 = "arduino";

Разрешени операции при деклариране на низове

  • Декларирайте символен масив, без да го инициализирате (Str1)
  • Декларирайте символен масив с един излишен елемент, компилаторът ще добави самия нулев символ (Str2)
  • Добавете нулев знак изрично (Str3)
  • Инициализирайте масива, използвайки низова константа в кавички; компилаторът ще създаде масив с необходимия размер с нулев знак в края (Str4)
  • Инициализирайте масив с помощта на низова константа, като изрично укажете неговия размер (Str5)
  • Инициализирайте масив с голям размер, оставяйки място за по-дълги низове (Str6)

Нулев завършващ символ

Обикновено всички низове са прекратени с нула (ASCII код 0), което позволява функции (напр Serial.print ()) определя дължината на низа. Без този знак те ще продължат да четат последователно байтове памет, които всъщност вече няма да са част от низа.

По принцип това означава, че вашият низ трябва да е с 1 знак по-дълъг от текста, който искате да съхраните в него. Ето защо Str2 и Str5 трябва да са дълги 8 знака, въпреки факта, че думата "arduino" е само 7 - последната позиция автоматично се запълва с нулев знак. Размерът на Str4 автоматично ще стане 8 - един знак е необходим за крайна нула. В ред Str3 независимо сме посочили нулев символ (означен с "\ 0").

Имайте предвид, че по принцип можете да декларирате низ без завършващ нулев символ (например, ако зададете дължината на Str2 на 7, а не на 8). Това обаче ще направи повечето от низовите функции неработоспособни, така че не трябва да правите това умишлено. Тази грешка може да причини странно поведение или появата на знаци от трети страни при работа с низове.

Единични или двойни кавички?

Низовете винаги се декларират в двойни кавички („Abc“), а знаците винаги се декларират в единични кавички („A“).

Увиване на дълги линии

Дългите редове могат да бъдат увити по следния начин:

Char myString = "Това е първият ред" "това е вторият ред" "и така";

Масиви от низове

Когато работите с големи количества текст (например в проекти, които работят с LCD екран), често е удобно да се използват масиви от низове. Тъй като низовете сами по себе си са масиви, това всъщност е пример за двуизмерен масив.

В следващата програма звездичката след типа данни char "char *" показва, че променливата е масив от "указатели". Всички имена на масиви всъщност са указатели, така че звездичката е необходима за създаване на масив от масиви. Указателите в C са едно от най-трудните неща за начинаещи, но в този случай не е необходимо да имате задълбочено разбиране на указателите, за да ги използвате ефективно.

Пример

char * myStrings = ("Това е низ 1", "Това е низ 2", "Това е низ 3", "Това е низ 4", "Това е низ 5", "Това е низ 6"); void setup () (Serial.begin (9600);) void loop () (за (int i = 0; i< 6; i++){ Serial.println(myStrings[i]); delay(500); } }