Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 14 - Textové řetězce v Javě do třetice - Split a join

V předešlém cvičení, Řešené úlohy k 13. lekci Javy, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V dnešním Java tutoriálu si vysvětlíme další metody na řetězci, které jsem vám záměrně zatajil, protože jsme nevěděli, že textový řetězec je vlastně pole :)

Metody na řetězci

Když si vytvoříme libovolnou proměnnou a napíšeme za ni poté tečku, zobrazí nám IDE 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:

  • Metody na textovém řetězci string v IntelliJ - Základní konstrukce jazyka Java
  • Metody na textovém řetězci string v NetBeans - Základní konstrukce jazyka Java

Tu samou nabídku lze vyvolat také stiskem kláves Ctrl + Mezerník v případě, že 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. NetBeans nám navíc zobrazuje i popis metod (co dělají) a jaké vyžadují parametry. Stejný popis můžeme v IntelliJ vyvolat tím, že najedeme šipkami na metodu, o které chceme vědět více, a stiskneme klávesy Ctrl + Q.

Řekněme si o následujících metodách a ukažme si je na jednoduchých příkladech.

Metoda substring()

Vrátí podřetězec od dané počáteční pozice do dané koncové pozice:

System.out.println("Wolfgang Amadeus Mozart".substring(9, 16));

Výstup:

Konzolová aplikace
Amadeus

Metoda compareTo()

Umožňuje porovnat dva řetězce podle abecedy. Vrací hodnotu -1, pokud je první řetězec před řetězcem v parametru, hodnotu 0, pokud jsou stejné a hodnotu 1, pokud je za ním:

System.out.println("Argentina".compareTo("Barbados"));

Výstup:

Konzolová aplikace
-1

Pojďme se nyní podívat na další metody, které jsou opravdu velmi užitečné.

Metody split() a join()

Z předchozího tutoriálu víme, že parsování řetězce 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ší textový řetězec (řádka souboru nebo řádka 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)

Význam jednotlivých řetězců:

  • 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 typu String můžeme volat metodu split(), která bere jako parametr separátor. Následně původní řetězec rozdělí podle separátorů 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 join() se volá přímo na typu String a umožňuje nám naopak pole podřetězců spojit oddělovačem do jediného řetězce, parametry jsou oddělovač a pole. Výstupem metody je výsledný řetězec.

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 morseovce. Písmena můžeme opět uložit do pouhého řetězce, 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
String sifrovanaZprava = ".-.. . --- -. .- .-. -.. ---";
System.out.printf("Původní zpráva: %s%n", sifrovanaZprava);
// řetězec s dekódovanou zprávou
String dekodovanaZprava = "";

// vzorová pole
String abeceda = "abcdefghijklmnopqrstuvwxyz";
String[] morseovyZnaky = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
"..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-",
"...-", ".--", "-..-", "-.--", "--.."};

Můžete si potom přidat další znaky jako čísla a interpunkční znaménka, my je zde vynecháme.

Nyní si řetězec sifrovanaZprava rozbijeme metodou split() na pole podřetězců, obsahujících jednotlivé znaky morseovky. Rozdělovat budeme podle znaku mezery. Pole následně proiterujeme cyklem foreach:

// rozbití řetězce na znaky morseovky
String[] znaky = sifrovanaZprava.split(" ");

// iterace znaky morseovky
for (String morseuvZnak : 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í). Metoda 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 tutoriálu nebudeme zabývat.

V cyklu se pokusíme najít aktuálně čtený znak morseovky v poli morseovyZnaky. Bude nás zajímat jeho index, protože když se podíváme na ten samý index v poli abeceda, 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:

char abecedniZnak = '?';

int index = -1;
for (int i = 0; i < morseovyZnaky.length; i++) {
    if (morseovyZnaky[i].equals(morseuvZnak))
        index = i;
}

if (index >= 0) { // znak nalezen
    abecedniZnak = abeceda.charAt(index);
}
dekodovanaZprava += abecedniZnak;

Kód nejprve do abecedního znaku uloží znak ?, protože se může stát, že znak v naší sadě nemáme. Následně se pokusíme zjistit jeho index. Pole v Javě bohužel nemá metodu indexOf() a zatím nechci zabíhat do složitějších datových struktur. Napíšeme si tedy vyhledání typu String v poli sami, bude to docela jednoduché.

Vyhledání řetězce v poli

Nejprve nastavíme index na -1, protože nevíme, jestli pole daný String (morseův znak) obsahuje. Následně pole projedeme cyklem a budeme kontrolovat jednotlivé řetězce s naším stringem (znakem). Již víme, že musíme k porovnání dvou řetězců použít metodu equals(). Pokud řetězce souhlasí, uložíme si aktuální index.

Pokud jsme znak našli (index >= 0), dosadíme do proměnné abecedniZnak znak z abecedy pod tímto indexem. Nakonec znak připojíme ke zprávě. Operátor += nahrazuje zprava = zprava + abecedniZnak.

Závěrem samozřejmě zprávu vypíšeme:

System.out.printf("Dekódovaná zpráva: %s%n", dekodovanaZprava);

Výstup programu:

Konzolová aplikace
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 morseovky, kód bude velmi podobný. S metodami split() a join() se potkáme během Java 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 sekvence \n, který kdekoli v textu způsobí odřádkování a poté \t, kde se jedná o tabulátor. Sekvenci \n do kódu často nepíšeme a využijeme raději formátový specifikátor %n, který způsobí správné odřádkování na specifických platformách. Pojďme si to vyzkoušet:

System.out.println("První řádka\nDruhá řádka");

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 "\uxxxx", kde xxxx je kód znaku.

Problém může nastat ve chvíli, když chceme napsat samotné lomítko \, musíme ho tzv. odescapovat:

System.out.println("Toto je zpětné lomítko: \\");

Stejným způsobem můžeme odescapovat např. uvozovku tak, aby ji Java nechápala jako konec řetězce:

System.out.println("Toto je uvozovka: \"");

Vstupy z konzole a polí v okenních aplikacích se samozřejmě escapují samy, aby uživatel nemohl zadat sekvenci \n a podobně. V kódu to má programátor povoleno a musí na to myslet.

Tímto jsme v podstatě zakončili kurz se základní strukturou jazyka Java. V příštích lekcích si uvedeme vícerozměrná pole a matematické operace. Ze základních konstrukcí jazyka vás tu ale již nic nepřekvapí :) V podstatě byste již klidně mohli jít i na objekty, doporučuji ale zbylé tutoriály ještě alespoň projet, jedná se přeci jen stále o základní znalosti, které byste měli mít.

V následujícím kvízu, Kvíz - Textové řetězce v Javě, 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 1253x (9.75 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Řešené úlohy k 13. lekci Javy
Všechny články v sekci
Základní konstrukce jazyka Java
Přeskočit článek
(nedoporučujeme)
Kvíz - Textové řetězce v Javě
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
554 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity