10. diel - Textové reťazce v jazyku C ++ druhýkrát - Práca so znakmi
V minulej lekcii, Textové reťazce v jazyku C ++ , sme si predstavili dátový typ
string
a funkcie, ktoré môžeme pre prácu s textovými
reťazcami používať.
Dnes budeme v C ++ tutoriálu pokračovať v práci s textom a zabavíme sa o tzv. ASCII hodnote. Vytvoríme tiež ďalšie praktické programy.
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
(1 byte, v C
/ C ++ typ char
), 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. Avšak v C ++ sa v predvolenom nastavení stále pracuje s ASCII
hodnotami jednotlivých znakov. Ak by sme chceli pracovať s UNICODE znaky (teda
i UTF8), museli by sme použiť takzvané wide znaky. Hlavná výhoda ASCII
zápisu je v tom, že znaky sú uložené v tabuľke za sebou, podľa abecedy.
Napr. na pozícii 97
nájdeme 'a'
, 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ť:
{CPP_CONSOLE}
char c; // znak
int i; // ordinálna (ASCII) hodnota znaku
// prevedieme znak na jeho ASCII hodnotu
c = 'a';
i = (int)c;
cout << "Znak " << c << " sme previedli na ASCII hodnotu "<< i << endl;
// Prevedieme ASCII hodnotu na znak
i = 98;
c = (char)i;
cout << "Ascii hodnotu " << i << " sme previedli na znak " << c << endl;
cin.get();
{/CPP_CONSOLE}
výsledok:
Konzolová aplikácia
Znak a sme previedli na ASCII hodnotu 97
Ascii hodnotu 98 sme previedli na znak b
Analýza výskytov vo vete
Napíšme si jednoduchý program, ktorý nám analyzuje zadanú vetu. Bude
nás zaujímať počet samohlások, spoluhlások, písmen a počet zvyšný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
reťazec za cin
. 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, spoluhlásky a písmená.
Počet zvyšných znakov nemusíme počítať, bude to dĺžka reťazca mínus
súčet samohlások, spoluhlások a písmen. Pripravíme 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. Tiež si nezabudnite includovat
knižnicu string
.
// inicializácia pocítadiel int pocetSamohlasek = 0; int pocetSouhlasek = 0; int pocetCisel = 0; // retazec, ktory chceme analyzovať string retezec = "Mount Everest"; // definícia typu znaku string samohlasky = "aeiouyAEIOUY"; string souhlasky = "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ"; string cisla = "0123456789"; cout << "Povodnej sprava: " << retezec << endl; // hlavni cyklus pokracuje, kým nenarazí na znak konca retazca for (int i = 0; i < retezec.length(); i++) { }
Najskôr počítadlo vynulujeme. Na definícia znakov nám postačí obyčajné pole znakov ako ho poznáme. Hlavný cyklus nám prejde jednotlivé znaky v reťazci. Poďme plniť počítadla, pre jednoduchosť už nebudem opisovať zvyšok kódu a presunu sa len k cyklu:
// hlavni cyklus pokracuje, kým nenarazí na znak konca retazca for (int i = 0; i < retezec.length(); i++) { if (samohlasky.find(retezec[i]) < samohlasky.length()) pocetSamohlasek++; else if (souhlasky.find(retezec[i]) < souhlasky.length()) pocetSouhlasek++; else if (cisla.find(retezec[i]) < cisla.length()) pocetCisel++; }
Všimnite si, že využívame metódu find()
, ktorá
zistí či reťazec obsahuje určitý znak.
Aktuálny znak 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. Vráťme sa k nášmu kódu vo funkcii
main()
. Teraz nám chýba už len výpis na koniec:
{CPP_CONSOLE}
// inicializace pocitadel
int pocetSamohlasek = 0;
int pocetSouhlasek = 0;
int pocetCisel = 0;
// retazec, ktory chceme analyzovať
string retezec = "Mount Everest";
// definícia typu znaku
string samohlasky = "aeiouyAEUOUY";
string souhlasky = "bcdfghijklmnpqrstvwxzBCDFGHIJKLMNPQRSTVWXZ";
string cisla = "0123456789";
cout << "Povodnej sprava: " << retezec << endl;
// hlavni cyklus pokracuje, kým nenarazí na znak konca retazca
for (int i = 0; i < retezec.length(); i++)
{
if (samohlasky.find(retezec[i]) < samohlasky.length())
pocetSamohlasek++;
else if (souhlasky.find(retezec[i]) < souhlasky.length())
pocetSouhlasek++;
else if (cisla.find(retezec[i]) < cisla.length())
pocetCisel++;
}
cout << "Pocet samohlások: " << pocetSamohlasek << endl;
cout << "Pocet spoluhlások: " << pocetSouhlasek << endl;
cout << "Počet čísiel: " << pocetCisel << endl;
cout << "Pocet zvyšných znaku: " <<
retezec.length() - pocetSamohlasek - pocetSouhlasek - pocetCisel << endl;
{/CPP_CONSOLE}
výsledok:
Konzolová aplikácia
Povodnej sprava: Mount Everest
Pocet samohlások: 5
Pocet spoluhlások: 7
Počet čísiel: 0
Pocet zvyšných znaku: 1
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 a pre posun. Zašifrovaným textom nahradíme pôvodnú
správu. Ď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
tým čo zadal užívateľ pomocou objektu cin
. Šifra nepočíta s
diakritikou, medzier a interpunkčných znamienok. Diakritiku budeme bojkotovať
a budeme predpokladať, že ju užívateľ nebude zadávať. Pre zjednodušenie
vynecháme aj veľké písmená. Ideálne by sme mali diakritiku pred
šifrovaním odstrániť, rovnako tak hocičo okrem písmen.
// retazec k zašifrovanie string s = "gaiusjuliuscaesar"; int posun = 1; cout << "Povodnej sprava: " << s << endl; // hlavni cyklus for (int i = 0; i < s.length(); i++) { } cout << "Zašifrovanú správu: " << s << endl; cin.get();
Teraz sa presunieme dovnútra cyklu. Hodnotu aktuálneho znaku zvýšime o posun a uložíme miesto pôvodného znaku.
{CPP_CONSOLE}
// retazec k zašifrovanie
string s = "gaiusjuliuscaesar";
int posun = 1;
cout << "Povodnej sprava: " << s << endl;
// hlavni cyklus
for (int i = 0; i < s.length(); i++)
{
s[i] = s[i] + posun;
}
cout << "Zašifrovanú správu: " << s << endl;
cin.get();
{/CPP_CONSOLE}
Konzolová aplikácia
Povodnej sprava: gaiusjuliuscaesar
Zašifrovanú správu: 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'
.
// hlavni cyklus for (int i = 0; i < s.length(); i++) { s[i] = s[i] + posun; if (s[i] > 'z') // kontrola pretečeniu s[i] = s[i] - 26; }
Ak hodnota presiahne ASCII hodnotu 'z'
, znížime ju o
26
znakov (toľko znakov má anglická abeceda). Je to jednoduché
a náš program je teraz funkčná. Všimnime si, že nikde nepoužívame priame
kódy znakov, v podmienke je '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 9.-10. lekciu C ++, 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é 96x (4.29 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C++