IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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í.

10. diel - Textové reťazce v C # druhýkrát - Práca s jednotlivými znakmi

V predchádzajúcom cvičení, Riešené úlohy k 9. lekcii C # .NET, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

Ak ste vycítili v C# nejakú podobnosť medzi poľom a textovým reťazcom, tak ste vycítili správne. Pre ostatné môže byť prekvapením, že string je v podstate pole znakov (hodnôt typu char) a môžeme s ním aj takto pracovať.

Najprv si vyskúšajme, že to všetko funguje. Rozcvičíme sa na jednoduchom vypísanie znaku na danej pozícii:

string s = "C# .NET";
Console.WriteLine(s);
Console.WriteLine(s[1]);
Console.ReadKey();

výstup:

C# .NET
#

Vidíme, že môžeme ku znakom v reťazci pristupovať cez hranatú zátvorku, ako tomu je aj u pole. Sklamaním môže byť, že znaky na danej pozícii sú v C# read-only, nemôžeme teda napísať:

string s = "C# .NET";
s[1] = '!';
Console.WriteLine(s);
Console.ReadKey();

Samozrejme to ide urobiť inak, neskôr si to ukážeme, zatiaľ sa budeme venovať iba čítanie jednotlivých znakov.

Analýza výskytu znakov vo vete

Napíšme si jednoduchý program, ktorý nám analyzuje zadanú vetu. Bude nás zaujímať počet samohlások, spoluhlások a počet nepísmenných znakov (napr. Medzera alebo !).

Daný textový reťazec si najprv v programe zadáme napevno, aby sme ho nemuseli pri každom spustení písať. Keď bude program hotový, nahradíme ho Console.ReadLine(). Reťazec budeme prechádzať cyklom po jednom znaku. Rovno tu hovorím, že neapeluje na rýchlosť programu a budeme voliť názorná a jednoduché riešenia.

Najprv si pripravme kód, definujme si samohlásky a spoluhlásky. Počet ostatných znakov nemusíme počítať, bude to dĺžka reťazca mínus samohlásky a spoluhlásky. Aby sme nemuseli riešiť veľkosť písmen, celý reťazec na začiatku prevedieme na malé písmená. Pripravme si premenné, do ktorých budeme ukladať jednotlivé počty. Pretože sa jedná o zložitejší kód, nebudeme zabúdať na komentáre.

// reťazec, ktorý chceme analyzovať
string s = "Mount Everest";
Console.WriteLine(s);
s = s.ToLower();

// inicializácia počítadiel
int pocetSamohlasek = 0;
int pocetSouhlasek = 0;

// definícia typov znakov
string samohlasky = "aeiouyáéěíóúůý";
string souhlasky = "bcčdďfghjklmnpqrřsštťvwxzž";

// hlavný cyklus
foreach (char c in s)
{

}

Console.ReadKey();

Spočiatku si pripravíme reťazec a prevedieme ho na malé písmená. Počítadla vynulujeme. Na definícia znakov nám postačí obyčajné reťazca. Hlavný cyklus nám prejde jednotlivé znaky v reťazci s, pričom v každej iterácii cyklu bude v premennej c aktuálny znak.

Poďme plniť počítadla, pre jednoduchosť už nebudem opisovať zvyšok kódu a presunu sa len k cyklu:

// hlavný cyklus
foreach (char c in s)
{
    if (samohlasky.Contains(c))
        pocetSamohlasek++;
    else
    if (souhlasky.Contains(c))
        pocetSouhlasek++;
}

Metódu Contains() na reťazci už poznáme, ako parameter ju možno odovzdať ako podreťazec, tak priamo znak. Daný znak c našej vety teda najprv skúsime vyhľadať v reťazci samohlasky a prípadne zvýšiť ich počítadlo. Ak v samohláskach nie je, pozrieme sa do spoluhlások a prípadne opätovne zvýšime ich počítadlo.

Teraz nám chýba už len výpis na koniec:

Console.WriteLine("Samohlások: {0}", pocetSamohlasek);
Console.WriteLine("Spoluhlások: {0}", pocetSouhlasek);
Console.WriteLine("Nepísmenných znakov: {0}", s.Length - (pocetSamohlasek + pocetSouhlasek));
Konzolová aplikácia
Mount Everest
Samohlások: 5
Spoluhlások: 7
Nepísmenných znakov: 1

A je to!

Ascii hodnota

Možno ste už niekedy počuli o ASCII tabuľke. Najmä v ére operačného systému MS-DOS prakticky nebola iná možnosť, ako zaznamenávať text. Jednotlivé znaky boli uložené ako čísla typu byte, teda s rozsahom hodnôt od 0 do 255. V systéme bola uložená tzv. ASCII tabuľka, ktorá mala 256 znakov a každému ASCII kódu (číselnému kódu) priradzovala jeden znak.

Asi je vám jasné, prečo tento spôsob nebol platný dodnes. Do tabuľky sa jednoducho nevošli všetky znaky všetkých národných abecied. Teraz sa používa Unicode (UTF-8) kódovanie, kde sú znaky reprezentované trochu iným spôsobom. VC # máme možnosť pracovať s ASCII hodnotami jednotlivých znakov. Hlavná výhoda je v tom, že znaky sú uložené v tabuľke za sebou, podľa abecedy. Napr. na pozícii 97 nájdeme 'a', na 98 'b' a podobne. Podobne je to s číslami, diakritické znaky tam budú bohužiaľ len nejako rozhádzané.

Skúsme si teraz previesť znak do jeho ASCII hodnoty a naopak podľa ASCII hodnoty daný znak vytvoriť:

char c; // znak
int i; // ordinálna (ASCII) hodnota znaku
// prevedieme znak na jeho ASCII hodnotu
c = 'a';
i = (int)c;
Console.WriteLine("Znak {0} sme previedli na ASCII hodnotu {1}", c, i);
// Prevedieme ASCII hodnotu na znak
i = 98;
c = (char)i;
Console.WriteLine("Ascii hodnotu {1} sme previedli na znak {0}", c, i);
Console.ReadKey();

Prevodom sa hovorí pretypovanie, ale o tom sa bližšie zabavíme až neskôr.

Cézarova šifra

Vytvoríme si jednoduchý program pre šifrovanie textu. Ak ste niekedy počuli o Cézarově šifre, bude to presne to, čo si tu naprogramujeme. Šifrovanie textu spočíva v posúvaní znaku v abecede o určitý, pevne stanovený počet znakov. Napríklad slovo "ahoj" sa s posunom textu o 1 preloží ako "bipk". Posun umožníme užívateľovi vybrať. Algoritmus tu máme samozrejme opäť vysvetlený a to v článku Cézarova šifra. Program si dokonca môžete vyskúšať v praxi - Online cézarova šifra.

Vráťme sa k programovaniu a pripravme si kód. Budeme potrebovať premenné pre pôvodné text, zašifrovanú správu a pre posun. Ďalej cyklus prechádzajúce jednotlivé znaky a výpis zašifrované správy. Správu si necháme zapísanú napevno v kóde, aby sme ju nemuseli pri každom spustení programu písať. Po dokončení nahradíme obsah premennej metódou Console.ReadLine(). Šifra nepočíta s diakritikou, medzier a interpunkčných znamienok. Diakritiku budeme bojkotovať a budeme predpokladať, že ju užívateľ nebude zadávať. Ideálne by sme potom mali diakritiku pred šifrovaním odstrániť, rovnako tak hocičo okrem písmen.

// inicializácia premenných
string s = "gaiusjuliuscaesar";
Console.WriteLine("Pôvodná správa: {0}", s);
string zprava = "";
int posun = 1;

// cyklus prechádzajúce jednotlivé znaky
foreach(char c in s)
{

}

// výpis
Console.WriteLine("Zašifrované správa: {0}", zprava);
Console.ReadKey();

Teraz sa presunieme dovnútra cyklu, prevedieme znak v c na ASCII hodnotu (čiže ordinálna hodnotu), túto hodnotu zvýšime o posun a prevedieme späť na znak. Tento znak nakoniec pripojíme k výslednej správe:

int i = (int)c;
i += posun;
char znak = (char)i;
zprava += znak;
Konzolová aplikácia
Pôvodná správa: gaiusjuliuscaesar
Zašifrované správa: hbjvtkvmjvtdbftbs

Program si vyskúšame. Výsledok vyzerá celkom dobre. Skúsme si však zadať vyššiu posun alebo napísať slovo "zebra". Vidíme, že znaky môžu po 'z' pretiecť do ASCII hodnôt ďalších znakov, v texte teda už nemáme len písmená, ale ďalšie škaredé znaky. Uzavrieme znaky do kruhu tak, aby posun plynule po 'z' prešiel opäť k 'a' a ďalej. Postačí nám k tomu jednoduchá podmienka, ktorá od novej ASCII hodnoty odpočíta celú abecedu tak, aby sme začínali opäť na 'a'.

int i = (int)c;
i += posun;
// kontrola pretečeniu
if (i > (int)'z')
    i -= 26;
char znak = (char)i;
zprava += znak;

Ak i presiahne ASCII hodnotu 'z', znížime ho o 26 znakov (toľko znakov má anglická abeceda). Operátor -= vykoná to isté, ako keby sme napísali i = i - 26. Je to jednoduché a náš program je teraz funkčná. Všimnime si, že nikde nepoužívame priame kódy znakov, v podmienke je (int)'z', aj keď by sme tam mohli napísať rovno 122. Je to z dôvodu, aby bol náš program plne odtienený od explicitných ASCII hodnôt a bolo lepšie viditeľné, ako funguje. Cvične si skúste urobiť dešifrovanie.

V nasledujúcom cvičení, Riešené úlohy k 10. lekcii C # .NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 1435x (48.75 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
Riešené úlohy k 9. lekcii C # .NET
Všetky články v sekcii
Základné konštrukcie jazyka C # .NET
Preskočiť článok
(neodporúčame)
Riešené úlohy k 10. lekcii C # .NET
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
2 hlasov
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 sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity