Arduino - ciągi

Ciągi są używane do przechowywania tekstu. Mogą być używane do wyświetlania tekstu na wyświetlaczu LCD lub w oknie monitora szeregowego Arduino IDE. Ciągi znaków są również przydatne do przechowywania danych wejściowych użytkownika. Na przykład znaki, które użytkownik wpisuje na klawiaturze podłączonej do Arduino.

W programowaniu Arduino istnieją dwa typy ciągów -

  • Tablice znaków, które są takie same, jak łańcuchy używane w programowaniu w C.
  • Arduino String, który pozwala nam użyć obiektu string w szkicu.

W tym rozdziale nauczymy się ciągów znaków, obiektów i ich wykorzystania w szkicach Arduino. Pod koniec rozdziału dowiesz się, jakiego rodzaju sznurka użyć w szkicu.

Tablice znaków ciągów

Pierwszym typem ciągu, którego się nauczymy, jest łańcuch będący serią znaków danego typu char. W poprzednim rozdziale dowiedzieliśmy się, czym jest tablica; kolejny ciąg tego samego typu zmiennej przechowywany w pamięci. Łańcuch to tablica zmiennych typu char.

Łańcuch to specjalna tablica, która ma jeden dodatkowy element na końcu łańcucha, który zawsze ma wartość 0 (zero). Nazywa się to „ciągiem zakończonym wartością zerową”.

Przykład tablicy znaków ciągu

Ten przykład pokaże, jak utworzyć łańcuch i wydrukować go w oknie monitora szeregowego.

Example

void setup() {
   char my_str[6]; // an array big enough for a 5 character string
   Serial.begin(9600);
   my_str[0] = 'H'; // the string consists of 5 characters
   my_str[1] = 'e';
   my_str[2] = 'l';
   my_str[3] = 'l';
   my_str[4] = 'o';
   my_str[5] = 0; // 6th array element is a null terminator
   Serial.println(my_str);
}

void loop() { 

}

Poniższy przykład pokazuje, z czego składa się ciąg; tablica znaków ze znakami drukowalnymi i 0 jako ostatnim elementem tablicy, aby pokazać, że na tym kończy się ciąg. Ciąg można wydrukować w oknie monitora szeregowego Arduino IDE za pomocąSerial.println() i przekazując nazwę ciągu.

Ten sam przykład można napisać w wygodniejszy sposób, jak pokazano poniżej -

Example

void setup() {
   char my_str[] = "Hello";
   Serial.begin(9600);
   Serial.println(my_str);
}

void loop() {

}

W tym szkicu kompilator oblicza rozmiar tablicy ciągów, a także automatycznie kończy ciąg z zerem. Tablica, która ma sześć elementów i składa się z pięciu znaków, po których następuje zero, jest tworzona dokładnie w taki sam sposób, jak w poprzednim szkicu.

Manipulowanie tablicami łańcuchowymi

Możemy zmienić tablicę strun w szkicu, jak pokazano na poniższym szkicu.

Przykład

void setup() {
   char like[] = "I like coffee and cake"; // create a string
   Serial.begin(9600);
   // (1) print the string
   Serial.println(like);
   // (2) delete part of the string
   like[13] = 0;
   Serial.println(like);
   // (3) substitute a word into the string
   like[13] = ' '; // replace the null terminator with a space
   like[18] = 't'; // insert the new word
   like[19] = 'e';
   like[20] = 'a';
   like[21] = 0; // terminate the string
   Serial.println(like);
}

void loop() {

}

Wynik

I like coffee and cake
I like coffee
I like coffee and tea

Szkic działa w następujący sposób.

Tworzenie i drukowanie łańcucha

W powyższym szkicu tworzony jest nowy ciąg, a następnie drukowany do wyświetlenia w oknie Serial Monitor.

Skracanie sznurka

Łańcuch jest skracany poprzez zastąpienie 14-tego znaku w ciągu znakiem zerowym kończącym zero (2). To jest element numer 13 w tablicy ciągów liczący od 0.

Kiedy drukowany jest łańcuch, wszystkie znaki są drukowane do nowego zerowego kończącego zero. Pozostałe postacie nie znikają; nadal istnieją w pamięci, a tablica ciągów ma nadal ten sam rozmiar. Jedyną różnicą jest to, że każda funkcja, która działa z ciągami znaków, będzie widzieć ciąg tylko do pierwszego terminatora null.

Zmiana słowa w ciągu

Wreszcie szkic zastępuje słowo „ciasto” słowem „herbata” (3). Najpierw musi zastąpić zerowy terminator w miejscu takim jak [13] spacją, aby łańcuch został przywrócony do pierwotnie utworzonego formatu.

Nowe znaki zastępują „cak” w słowie „ciasto” słowem „herbata”. Odbywa się to poprzez nadpisywanie poszczególnych znaków. Litera „e” słowa „placek” jest zastępowana nowym znakiem kończącym wartość null. W rezultacie ciąg jest faktycznie zakończony dwoma znakami pustymi, oryginalnym na końcu łańcucha i nowym, który zastępuje „e” w słowie „ciasto”. Nie ma to znaczenia, kiedy drukowany jest nowy ciąg, ponieważ funkcja, która drukuje ciąg, przestaje drukować znaki ciągu, gdy napotka pierwszy terminator zerowy.

Funkcje do manipulowania tablicami ciągów

Poprzedni szkic manipulował łańcuchem w sposób ręczny, uzyskując dostęp do poszczególnych znaków w ciągu. Aby ułatwić manipulowanie tablicami łańcuchowymi, możesz napisać własne funkcje, aby to zrobić, lub użyć niektórych funkcji łańcuchowych zC biblioteka językowa.

S.No. Funkcje i opis
1

String()

Klasa String, będąca częścią rdzenia od wersji 0019, umożliwia używanie i manipulowanie ciągami tekstu w bardziej złożony sposób niż robią to tablice znaków. Możesz łączyć ciągi, dołączać do nich, wyszukiwać i zamieniać podciągi i nie tylko. Zajmuje więcej pamięci niż prosta tablica znaków, ale jest też bardziej przydatna.

Dla porównania tablice znaków są określane jako ciągi z małym „s”, a wystąpienia klasy String są określane jako ciągi z dużą literą S. Należy pamiętać, że ciągi stałe, określone w „cudzysłowach”, są traktowane jako tablice znaków, nie instancje klasy String

2

charAt()

Uzyskaj dostęp do określonego znaku String.

3

compareTo()

Porównuje dwa ciągi, sprawdzając, czy jeden występuje przed, po drugim lub czy są równe. Łańcuchy są porównywane znak po znaku przy użyciu wartości znaków ASCII. Oznacza to na przykład, że „a” występuje przed „b”, ale po „A”. Liczby poprzedzają litery.

4

concat()

Dołącza parametr do String.

5

c_str()

Konwertuje zawartość ciągu na ciąg w stylu C zakończony znakiem null. Zauważ, że daje to bezpośredni dostęp do wewnętrznego bufora String i powinno być używane z ostrożnością. W szczególności nigdy nie należy modyfikować ciągu znaków za pomocą zwróconego wskaźnika. Kiedy modyfikujesz obiekt String lub gdy jest on zniszczony, każdy wskaźnik poprzednio zwrócony przez c_str () staje się nieważny i nie powinien być już używany.

6

endsWith()

Sprawdza, czy String kończy się znakami innego Stringa.

7

equals()

Porównuje dwa ciągi pod kątem równości. W porównaniu rozróżniana jest wielkość liter, co oznacza, że ​​Ciąg „cześć” nie jest równy Ciągowi „HELLO”.

8

equalsIgnoreCase()

Porównuje dwa ciągi pod kątem równości. W porównaniu nie jest rozróżniana wielkość liter, co oznacza, że ​​Ciąg („cześć”) jest równy Ciągowi („HELLO”).

9

getBytes()

Kopiuje znaki ciągu do podanego buforu.

10

indexOf()

Lokalizuje znak lub ciąg w innym ciągu. Domyślnie wyszukuje od początku Stringa, ale może też zacząć od danego indeksu, pozwalając na zlokalizowanie wszystkich wystąpień znaku lub String.

11

lastIndexOf()

Lokalizuje znak lub ciąg w innym ciągu. Domyślnie wyszukuje od końca Stringa, ale może również pracować wstecz od danego indeksu, umożliwiając zlokalizowanie wszystkich wystąpień znaku lub String.

12

length()

Zwraca długość ciągu w znakach. (Należy pamiętać, że nie obejmuje to końcowego znaku null).

13

remove()

Modyfikuj w miejscu, ciąg usuwający znaki z podanego indeksu do końca ciągu lub z podanego indeksu do indeksu i liczby.

14

replace()

Funkcja String replace () umożliwia zastąpienie wszystkich wystąpień danego znaku innym znakiem. Możesz również użyć funkcji replace w celu zastąpienia podciągów łańcucha innym podciągiem.

15

reserve()

Funkcja String Reserve () umożliwia przydzielenie buforu w pamięci do manipulowania napisami.

16

setCharAt()

Ustawia znak String. Nie ma wpływu na indeksy poza istniejącą długością String.

17

startsWith()

Sprawdza, czy String zaczyna się od znaków innego String.

18

toCharArray()

Kopiuje znaki ciągu do podanego buforu.

19

substring()

Pobierz podciąg String. Indeks początkowy jest włącznie (odpowiedni znak jest zawarty w podłańcuchu), ale opcjonalny indeks końcowy jest wyłączny (odpowiedni znak nie jest zawarty w podłańcuchu). Jeśli indeks końcowy zostanie pominięty, podciąg jest kontynuowany do końca String.

20

toInt()

Konwertuje prawidłowy ciąg znaków na liczbę całkowitą. Ciąg wejściowy powinien zaczynać się liczbą całkowitą. Jeśli ciąg zawiera liczby niecałkowite, funkcja przestanie wykonywać konwersję.

21

toFloat()

Konwertuje prawidłowy ciąg znaków na liczbę zmiennoprzecinkową. Ciąg wejściowy powinien zaczynać się od cyfry. Jeśli ciąg zawiera znaki inne niż cyfry, funkcja przestanie wykonywać konwersję. Na przykład ciągi „123,45”, „123” i „123fish” są konwertowane odpowiednio na 123,45, 123,00 i 123,00. Zwróć uwagę, że wartość „123,456” jest przybliżona wartością 123,46. Zwróć też uwagę, że liczby zmiennoprzecinkowe mają tylko 6-7 cyfr dziesiętnych precyzji i że dłuższe ciągi mogą zostać obcięte.

22

toLowerCase()

Pobierz wersję String z małymi literami. Od wersji 1.0 toLowerCase () modyfikuje ciąg znaków w miejscu zamiast zwracać nowy.

23

toUpperCase()

Pobierz wersję String z dużymi literami. Od wersji 1.0 toUpperCase () modyfikuje ciąg znaków w miejscu zamiast zwracać nowy.

24

trim()

Pobierz wersję String z usuniętymi wszystkimi wiodącymi i końcowymi spacjami. Od wersji 1.0 trim () modyfikuje ciąg znaków w miejscu zamiast zwracać nowy.

W następnym szkicu użyto niektórych funkcji napisów C.

Przykład

void setup() {
   char str[] = "This is my string"; // create a string
   char out_str[40]; // output from string functions placed here
   int num; // general purpose integer
   Serial.begin(9600);

   // (1) print the string
   Serial.println(str);

   // (2) get the length of the string (excludes null terminator)
   num = strlen(str);
   Serial.print("String length is: ");
   Serial.println(num);

   // (3) get the length of the array (includes null terminator)
   num = sizeof(str); // sizeof() is not a C string function
   Serial.print("Size of the array: ");
   Serial.println(num);

   // (4) copy a string
   strcpy(out_str, str);
   Serial.println(out_str);

   // (5) add a string to the end of a string (append)
   strcat(out_str, " sketch.");
   Serial.println(out_str);
   num = strlen(out_str);
   Serial.print("String length is: ");
   Serial.println(num);
   num = sizeof(out_str);
   Serial.print("Size of the array out_str[]: ");
   Serial.println(num);
}

void loop() {

}

Wynik

This is my string
String length is: 17
Size of the array: 18
This is my string
This is my string sketch.
String length is: 25
Size of the array out_str[]: 40

Szkic działa w następujący sposób.

Wydrukuj ciąg

Nowo utworzony ciąg jest drukowany w oknie monitora szeregowego, tak jak w poprzednich szkicach.

Uzyskaj długość sznurka

Funkcja strlen () służy do uzyskania długości łańcucha. Długość ciągu dotyczy tylko drukowalnych znaków i nie zawiera terminatora null.

Ciąg zawiera 17 znaków, więc widzimy 17 wydrukowanych w oknie Serial Monitor.

Uzyskaj długość tablicy

Operator sizeof () służy do pobierania długości tablicy zawierającej ciąg. Długość obejmuje terminator null, więc długość jest o jeden większa niż długość ciągu.

sizeof () wygląda jak funkcja, ale technicznie jest operatorem. Nie jest częścią biblioteki ciągów C, ale został użyty w szkicu, aby pokazać różnicę między rozmiarem tablicy a rozmiarem ciągu (lub długością łańcucha).

Skopiuj ciąg

Funkcja strcpy () służy do kopiowania ciągu str [] do tablicy out_num []. Funkcja strcpy () kopiuje drugi przekazany do niej łańcuch do pierwszego. Kopia łańcucha istnieje teraz w tablicy out_num [], ale zajmuje tylko 18 elementów tablicy, więc nadal mamy w tablicy 22 wolne elementy typu char. Te wolne elementy znajdują się po ciągu w pamięci.

Ciąg został skopiowany do tablicy, abyśmy mieli dodatkowe miejsce w tablicy do wykorzystania w następnej części szkicu, czyli dodaniu ciągu na końcu łańcucha.

Dołącz ciąg do ciągu (konkatenacja)

Szkic łączy jeden ciąg z drugim, co jest znane jako konkatenacja. Odbywa się to za pomocą funkcji strcat (). Funkcja strcat () umieszcza drugi przekazany do niej ciąg na końcu pierwszego przekazanego do niej ciągu.

Po konkatenacji długość łańcucha jest wypisywana, aby pokazać nową długość łańcucha. Następnie wypisywana jest długość tablicy, aby pokazać, że mamy 25-znakowy ciąg w 40-elementowej tablicy.

Pamiętaj, że 25-znakowy ciąg w rzeczywistości zajmuje 26 znaków tablicy z powodu kończącego zero.

Array Bounds

Podczas pracy z łańcuchami i tablicami bardzo ważne jest, aby pracować w granicach ciągów lub tablic. W przykładowym szkicu utworzono tablicę o długości 40 znaków w celu przydzielenia pamięci, której można by użyć do manipulowania łańcuchami.

Jeśli tablica byłaby zbyt mała i próbowaliśmy skopiować do niej ciąg, który jest większy niż tablica, ciąg zostałby skopiowany na koniec tablicy. Pamięć poza końcem tablicy mogłaby zawierać inne ważne dane użyte w szkicu, które następnie zostałyby nadpisane przez nasz ciąg. Jeśli pamięć poza końcem łańcucha zostanie przepełniona, może to spowodować awarię szkicu lub nieoczekiwane zachowanie.