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 12 - Textové řetězce v JavaScriptu podruhé - Práce se znaky Nové

V minulé lekci, Nejčastější chyby JS začátečníků - Umíš pojmenovat proměnné?, jsme si ukázali nejčastější chyby začátečníků v JavaScriptu ohledně pojmenování proměnných.

V dnešním JavaScript tutoriálu se budeme zabývat přístupem k jednotlivým znakům textového řetězce a představíme si další metody pro práci s řetězci.

Textový řetězec

Pokud jste vycítili nějakou podobnost mezi polem a textovým řetězcem, tak jste vycítili správně. Pro ostatní může být překvapením, že je datový typ string v podstatě pole jednotlivých znaků a můžeme s ním i takto pracovat.

Pro přístup k jednotlivým znakům poskytuje JavaScript dvě metody:

  • charAt(index) – Tuto metodu použijeme pro získání znaku na určité pozici. V jejím parametru zadáme index znaku v řetězci (počínaje 0).
  • indexOf(znak) – Opakem je metoda indexOf(znak). Díky ní zjistíme index zadaného znaku. Jako parametr jí tedy předáme hledaný znak. Tato metoda vrací index prvního výskytu daného znaku a pokud jej v řetězci nenajde vrátí hodnotu -1.

Práce se znaky řetězce

Nejprve si vyzkoušejme, že to všechno funguje. Rozcvičíme se na jednoduchém vypsání znaku na dané pozici. Jednotlivé znaky v řetězci můžeme vybrat pomocí indexu. Index se zapisuje do hranatých závorek za názvem proměnné. Čísluje se od nuly, prvnímu znaku tedy odpovídá index [0]:

let jazyk = "JavaScript";
document.write(jazyk[0]); // vypíše první znak řetězce
document.write(jazyk[4]); // vypíše pátý znak řetězce

Výstup:

Tvoje stránka
localhost

Znaky na dané pozici jsou v JavaScriptu read-only, nemůžeme je tedy jednoduše změnit. Samozřejmě to jde udělat jinak, později si to ukážeme, zatím se budeme věnovat pouze čtení jednotlivých znaků.

Metoda charAt()

Znak na daném indexu můžeme nalézt také pomocí metody charAt() předchozí kód bychom zapsali takto:

let jazyk = "JavaScript";
document.write(jazyk.charAt(0));
document.write(jazyk.charAt(4));

V praxi použijeme spíše první zápis. Pokud v něm zadáme neplatný index (v našem případě například číslo 15), získáme hodnotu undefined. Oproti tomu metoda charAt() v takovém případě vrátí prázdný řetězec.

Výstup:

Tvoje stránka
localhost

Metoda indexOf()

A nyní se podíváme na zjištění indexu zadaného znaku. Jak jsme již zmínili v úvodu lekce, využijeme metodu indexOf().

Zkusme si vypsat index znaku a, s a nějaký znak, který v textu není, například x:

let jazyk = "JavaScript";
document.write(jazyk.indexOf("a"));
document.write("<br />");
document.write(jazyk.indexOf("s"));
document.write("<br />");
document.write(jazyk.indexOf("x"));

Výstup:

Tvoje stránka
localhost

Vidíme, že znak s v textu JavaScript nebyl nalezen. Metoda indexOf() totiž rozlišuje mezi velkými a malými písmeny. Pokud bychom jí v parametru zadali velké S, získali bychom index 4.

Metoda lastIndexOf()

Chceme-li zjistit poslední index daného znaku nebo podřetězce, použijeme metodu lastIndexOf():

let jazyk = "JavaScript";
document.write(jazyk.lastIndexOf("a"));

Výstup:

Tvoje stránka
localhost

Metoda substring()

Nyní si ještě ukážeme, jak získat vybranou část řetězce, které se říká podřetězec:

let skladatel = "Wolfgang Amadeus Mozart";
document.write(skladatel.substring(9, 16));

Výstup:

Tvoje stránka
localhost

V JS existovala také metoda substr(), která je nyní označena jako zastaralá.

ASCII hodnota

Možná jste již někdy slyšeli o ASCII tabulce. Zejména v éře operačního systému MS-DOS prakticky nebyla jiná možnost, jak zaznamenávat text. Jednotlivé znaky byly uloženy jako čísla typu byte, tedy s rozsahem hodnot od 0 do 255. V systému byla uložena tzv. ASCII tabulka, která měla také 256 znaků a každému ASCII kódu (číselnému kódu) přiřazovala jeden znak.

Asi je vám jasné, proč tento způsob nepřetrval dodnes. Do tabulky se jednoduše nevešly všechny znaky všech národních abeced, nyní se používá Unicode (UTF-8) kódování, kde jsou znaky reprezentovány trochu jiným způsobem. Nicméně máme stále možnost pracovat s ASCII hodnotami jednotlivých znaků. Hlavní výhoda je v tom, že znaky jsou uloženy v tabulce za sebou, podle abecedy. Např. na pozici 97 nalezneme znak a, na pozici 98 znak b a podobně. Podobně je to s čísly, diakritické znaky tam budou bohužel jen nějak rozházeny.

Zkusme si nyní převést znak do jeho ASCII hodnoty. Využijeme k tomu metodu charCodeAt() a jako parametr jí zadáme index 0:

let znak = "a";
let hodnotaAscii = znak.charCodeAt(0); // Převede znak na jeho ASCII hodnotu
document.write(`Znak '${znak}' jsme převedli na ASCII hodnotu ${hodnotaAscii}`);

Výstup:

Tvoje stránka
localhost

Pomocí metody String.fromCharCode() naopak vytvoříme určitý znak, když jí v parametru zadáme číselnou ASCII hodnotu:

let hodnotaAscii = 98;
let znak = String.fromCharCode(hodnotaAscii); // Převede ASCII hodnotu na znak
document.write(`ASCII hodnotu ${hodnotaAscii} jsme převedli na znak '${znak}'`);

Výstup:

Tvoje stránka
localhost

Caesarova šifra

Nakonec si vytvoříme jednoduchý program pro šifrování textu. Pokud jste někdy slyšeli o Caesarově šifře, bude to přesně to, co si zde naprogramujeme. Šifrování textu spočívá v posouvání znaku v abecedě o určitý, pevně stanovený, počet znaků. Například slovo ahoj se s posunem textu o 1 přeloží jako "bipk". Posun umožníme uživateli vybrat. Algoritmus zde máme samozřejmě opět vysvětlený a to v článku Caesarova šifra. Program si dokonce můžete vyzkoušet v praxi - Online caesarova šifra.

Vraťme se k programování a připravme si kód. Budeme potřebovat proměnné pro:

  • původní text,
  • zašifrovanou zprávu
  • a pro posun.

Dále si připravíme cyklus projíždějící jednotlivé znaky a výpis zašifrované zprávy. Zprávu si necháme zapsanou napevno v kódu, abychom ji nemuseli při každém spuštění programu psát. Šifra nepočítá s diakritikou, mezerami a interpunkčními znaménky:

// inicializace proměnných
let puvodniZprava = "gaiusjuliuscaesar";
document.write("Původní zpráva: " + puvodniZprava);
document.write("<br />");

let zasifrovanaZprava = "";
let posun = 1;

// cyklus projíždějící jednotlivé znaky
for (let i = 0; i < puvodniZprava.length; i++) {
    // ...
}

// výpis
document.write("Zašifrovaná zpráva: " + zasifrovanaZprava);

Nyní se přesuneme dovnitř cyklu, v něm postupně získáme ASCII hodnotu (neboli ordinální hodnotu) jednotlivých znaků, tuto hodnotu pokaždé zvýšíme o posun a převedeme na znak. Tento znak nakonec připojíme k výsledné zprávě:

// inicializace proměnných
let puvodniZprava = "gaiusjuliuscaesar";
document.write("Původní zpráva: " + puvodniZprava);
document.write("<br />");

let zasifrovanaZprava = "";
let posun = 1;

// cyklus projíždějící jednotlivé znaky
for (let i = 0; i < puvodniZprava.length; i++) {
    let ascii = puvodniZprava.charCodeAt(i);
    ascii += posun;
    let znak = String.fromCharCode(ascii);
    zasifrovanaZprava += znak;
}

// výpis
document.write("Zašifrovaná zpráva: " + zasifrovanaZprava);

Výstup programu:

Tvoje stránka
localhost

Program si vyzkoušíme. Výsledek vypadá docela dobře. Zkusme si však zadat vyšší posun nebo napsat slovo zebra. Vidíme, že znaky mohou po z přetéct do ASCII hodnot dalších znaků, v textu tedy již nemáme jen písmena, ale další ošklivé znaky.

Doplnění kontroly přetečení

Problém vyřešíme tím, že uzavřeme znaky do kruhu tak, aby posun plynule po znaku z přešel opět ke znaku a a podobně. Postačí nám k tomu jednoduchá podmínka, která od nové ASCII hodnoty odečte celou abecedu tak, abychom začínali opět na a. Upravený cyklus bude vypadat takto:

for (let i = 0; i < puvodniZprava.length; i++) {
    let ascii = puvodniZprava.charCodeAt(i);
    ascii += posun;
    // Kontrola přetečení
    if (ascii > "z".charCodeAt(0)) {
        ascii -= 26;
    }
    let znak = String.fromCharCode(ascii);
    zasifrovanaZprava += znak;
}

Pokud hodnota proměnné ascii přesáhne ASCII hodnotu z, snížíme ji o 26 znaků (tolik znaků má anglická abeceda). Operátor -= vykoná to samé, jako bychom napsali ascii = ascii - 26. Je to jednoduché a náš program je nyní funkční.

Jako původní zprávu nastavíme text zebra a v prohlížeči pak program znovu spustíme:

Tvoje stránka
localhost

Všimněme si, že nikde nepoužíváme přímé kódy znaků, v podmínce je ascii > "z".charCodeAt(0), i když bychom tam mohli napsat rovnou 122. Je to z důvodu, aby byl náš program plně odstíněn od explicitních ASCII hodnot a bylo lépe viditelné, jak funguje. Cvičně si zkuste udělat dešifrování :)

V příští lekci, Textové řetězce v JavaScriptu do třetice - Split a join, si ukážeme, že string umí přeci jen ještě něco navíc. Prozradím, že budeme dekódovat Morseovu abecedu.


 

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 29x (2.94 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
Nejčastější chyby JS začátečníků - Umíš pojmenovat proměnné?
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Přeskočit článek
(nedoporučujeme)
Textové řetězce v JavaScriptu do třetice - Split a join
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
87 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