Lekce 10 - Textové řetězce v Kotlin do třetice - Split
V předešlém cvičení, Řešené úlohy k 9. lekci Kotlin, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
Dnes si v Kotlin tutoriálu vysvětlíme další metody na řetězci, které
jsem vám záměrně zatajil, protože jsme nevěděli, že String
je vlastně pole
Na řetězci můžeme používat mnoho metod nebo vlastností, které známe
z pole. Jsou to např: first()
, last()
,
indexOf()
a další.
Když si vytvoříme libovolnou proměnnou a napíšeme za ni tečku, IntelliJ IDEA nám zobrazí nabídku všech metod a vlastností (a také proměnných, ale k tomu se dostaneme až u objektů), které na ni můžeme volat. Zkusme si to:

Tu samou nabídku lze vyvolat také stiskem Ctrl + Mezerník v případě, že textový kurzor umístíme na tečku. Samozřejmě to platí pro všechny proměnné i třídy a budeme toho využívat stále častěji. Metody jsou řazené abecedně a můžeme jimi listovat pomocí kurzorových šipek. IntelliJ nám zobrazuje popis metod (co dělají) a jaké vyžadují parametry.
Řekněme si o následujících metodách a ukažme si je na jednoduchých příkladech:
Další metody na řetězci
substring()
Vrátí podřetězec od dané počáteční pozice do dané koncové pozice.
{KOTLIN_CONSOLE}
println("Wolfgang Amadeus Mozart".substring(9, 16))
{/KOTLIN_CONSOLE}
Výstup:
Amadeus
compareTo()
Umožňuje porovnat dva řetězce podle abecedy. Vrací -1
pokud
je první řetězec před řetězcem v parametru, 0
pokud jsou
stejné a 1
pokud je za ním:
{KOTLIN_CONSOLE}
println("argentina".compareTo("barbados"))
{/KOTLIN_CONSOLE}
Výstup:
-1
Pojďme se nyní podívat na další metodu na String
, která je
opravdu velmi užitečná.
split()
a
joinToString()
Z předchozího tutoriálu víme, že parsování řetězce znak po znaku
může být někdy docela složité a to jsme dělali poměrně jednoduchý
příklad. S řetězci se samozřejmě budeme setkávat stále, a to jak na
vstupu od uživatele (např. z konzole nebo z polí v okenních aplikacích),
tak v souborech TXT a XML. Velmi často máme zadán jeden delší
String
(řádek souboru nebo řádek konzole), ve kterém je více
hodnot, oddělených tzv. separátory, např. čárkou. V tomto případě
hovoříme o formátu CSV (Comma-Separated Values, tedy hodnoty oddělené
čárkou). Abychom si byli jisti, že víme, o čem hovoříme, ukažme si
nějaké ukázkové řetězce:
Jan,Novák,Dlouhá 10,Praha 3,130 00 .. ... .-.. .- -. -.. ... --- ..-. - (1,2,3;4,5,6;7,8,9)
- První řetězec je očividně nějaký uživatel, takto bychom mohli např. realizovat uložení uživatelů do CSV souboru, každý na jeden řádek.
- Druhý řetězec jsou znaky Morseovy abecedy, separátor (oddělovač) je zde mezera.
- Třetí řetězec je matice o 3 sloupcích a 3 řádcích. Oddělovač sloupců je čárka, řádků středník.
Na String
můžeme volat metodu split()
, která
bere jako parametr separátor (typu Char
). Následně původní
řetězec rozdělí podle separátoru na pole podřetězců, které vrátí. To
nám velmi ulehčí práci při rozdělování hodnot v řetězci.
Metoda joinToString()
nám naopak umožňuje pole podřetězců
spojit oddělovačem do jediného řetězce, parametr je oddělovač. Výstupem
metody je výsledný řetězec. Metodu můžeme zavolat bez parametru a tím
dojde ke spojení řetězců bez oddělovače.
Jelikož neumíme tvořit objekty (uživatele) a ani pracovat s vícerozměrnými poli (matice), zkusíme si naprogramovat dekodér zpráv z Morseovy abecedy.
Dekodér Morseovy abecedy
Pojďme si opět připravit strukturu programu. Budeme potřebovat 2
řetězce se zprávou, jeden se zprávou v Morseově abecedě, druhý zatím
prázdný, do kterého budeme ukládat výsledek našeho snažení. Dále budeme
jako v případě samohlásek potřebovat nějaký vzor písmen. K písmenům
samozřejmě vzor jejich znaku v morzeovce. Písmena můžeme opět uložit do
pouhé proměnné typu String
, protože mají jen jeden znak. Znaky
Morseovy abecedy mají již znaků více, ty musíme dát do pole.
Struktura našeho programu by nyní mohla vypadat následovně:
// řetězec, který chceme dekódovat val s = ".-.. . --- -. .- .-. -.. ---" println("Původní zpráva: $s") // řetězec s dekódovanou zprávou var zprava = "" // vzorová pole val abecedniZnaky = "abcdefghijklmnopqrstuvwxyz" val morseovyZnaky = arrayOf(".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..")
Můžete si potom přidat další znaky jako čísla a interpunkční
znaménka, my je zde vynecháme. Nyní si řetězec s
rozbijeme
metodou split()
na pole podřetězců, obsahujících jednotlivé
znaky morzeovky. Splitovat budeme podle znaku mezery. Pole následně
proiterujeme cyklem for
:
// rozbití řetězce na znaky morzeovky val znaky = s.split(" ") // iterace znaků morzeovky for (morseuvZnak in znaky) { }
Ideálně bychom se měli nějak vypořádat s případy, kde uživatel zadá
např. více mezer mezi znaky (to uživatelé rádi dělají).
split()
poté vytvoří o jeden řetězec v poli více, který bude
prázdný. Ten bychom měli poté v cyklu detekovat a ignorovat, my se s tím v
Kotlin tutoriálu nebudeme zabývat.
V cyklu se pokusíme najít aktuálně čtený znak morzeovky v poli
morseovyZnaky
. Bude nás zajímat jeho index,
protože když se podíváme na ten samý index v řetězci
abecedniZnaky
, bude tam odpovídající písmeno. To je
samozřejmě z toho důvodu, že jak pole tak řetězec obsahují stejné znaky,
seřazené dle abecedy. Umístěme do těla cyklu následující kód:
val index = morseovyZnaky.indexOf(morseuvZnak) // Zkontrolování, že jsme index našli if (index != -1) { zprava += abecedniZnaky[index] }
Pokusíme se zjistit index morseova znaku. Pokud se to podaří, najdeme v
abecedě odpovídající písmeno a to přidáme do zprávy. Operátor
+=
nahrazuje
zprava = zprava + abecedniZnaky[index]
.
Závěrem samozřejmě zprávu vypíšeme:
{KOTLIN_CONSOLE}
// řetězec, který chceme dekódovat
val s = ".-.. . --- -. .- .-. -.. ---"
println("Původní zpráva: $s")
// řetězec s dekódovanou zprávou
var zprava = ""
// vzorová pole
val abecedniZnaky = "abcdefghijklmnopqrstuvwxyz"
val morseovyZnaky = arrayOf(".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..")
// rozbití řetězce na znaky morzeovky
val znaky = s.split(" ")
// iterace znaky morzeovky
for (morseuvZnak in znaky) {
val index = morseovyZnaky.indexOf(morseuvZnak)
// Zkontrolování, že jsme index našli
if (index != -1) {
zprava += abecedniZnaky[index]
}
}
println("Dekódovaná zpráva: $zprava")
{/KOTLIN_CONSOLE}
Výstup:
Původní zpráva: .-.. . --- -. .- .-. -.. --- Dekódovaná zpráva: leonardo
Hotovo! Za úkol máte si naprogramovat program opačný, který naopak
zakóduje řetězec do morzeovky, kód bude velmi podobný. Se
split()
a joinToString()
se potkáme během Kotlin
kurzu ještě několikrát.
Speciální znaky a escapování
Textový řetězec může obsahovat speciální znaky, které jsou
předsazené zpětným lomítkem \
. Je to zejména znak
\n
, který kdekoli v textu způsobí odřádkování a poté
\t
, kde se jedná o tabulátor.
Pojďme si to vyzkoušet:
{KOTLIN_CONSOLE}
println("První řádka\nDruhá řádka")
{/KOTLIN_CONSOLE}
Znak \
označuje nějakou speciální sekvenci znaků v
řetězci a je dále využíván např. k psaní unicode znaku jako
\u{xxxx}
, kde xxxx
je kód znaku.
Problém může nastat ve chvíli, když chceme napsat samotné
\
, musíme ho tzv. odescapovat:
{KOTLIN_CONSOLE}
println("Toto je zpětné lomítko: \\")
{/KOTLIN_CONSOLE}
Stejným způsobem můžeme odescapovat např. uvozovku tak, aby ji Kotlin nechápal jako konec řetězce:
{KOTLIN_CONSOLE}
println("Toto je uvozovka: \"")
{/KOTLIN_CONSOLE}
Vstupy z konzole a polí v okenních aplikacích se samozřejmě escapují
samy, aby uživatel nemohl zadat \n
a podobně. V kódu to má
programátor povoleno a musí na to myslet.
Raw string
Občas potřebujeme zapsat více zpětných lomítek v jednom textovém
řetězci. Kdybychom je všechny escapovali, mohlo by to znepřehlednit náš
kód. Kvůli tomuto problému lze v Kotlin deklarovat tzv. Raw string. Stačí
obalit text do """
a veškerá zpětné lomítka se chovají jako
obyčejné znaky.
{KOTLIN_CONSOLE}
println("""V tomto stringu nemusím nic escapovat \""")
{/KOTLIN_CONSOLE}
V následujícím kvízu, Kvíz - Textové řetězce v Kotlin, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 44x (7.71 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin