Java týden
Procvič si angličtinu zdarma s naším americkým e-learningem! Learn more
Pouze tento týden sleva až 80 % na celý Java e-learning!

Lekce 9 - Textové řetězce v jazyce C++

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Pole v C++, jsme si představili pole. S textovými řetězci jsme se již v kurzu letmo setkali, načítali jsme je a vypisovali pomocí proměnné typu string. S řetězci lze v C++ pracovat několika způsoby. My si v tomto C++ tutoriálu uvedeme zatím ten nejjednodušší, tzv. statický řetězec, kterým je právě typ string.

Knihovna string

Když budeme chtít uložit do proměnné textový řetězec "Hello ITnetwork", pouze vytvoříme objekt typu string a přiřadíme mu řetězec. Zatím nás nemusí trápit, že vlastně nevíme, co objekt je. Dozvíte se to v sekci věnované OOP. Nesmíme zapomenout includovat hlavičkový soubor string:

#include <string>
#include <iostream>
using namespace std;

int main()
{
    string pozdrav = "Hello World!";
    cout << pozdrav << endl;
    cin.get();
    return 0;
}

Tak jak jsme to v C++ viděli již několikrát, vypsaný text se objeví na obrazovce a čeká se na stisknutí klávesy od uživatele.

Konzolová aplikace
Hello Wordl!

Práce s jednotlivými znaky

S řetězcem můžeme zacházet úplně stejně jako s polem, protože interně polem je :) Není tedy problém vypsat například první znak nebo znaky měnit. Při jiné manipulaci s řetězci je lepší použít metody (funkce), které typ string poskytuje. My si na konci uvedeme ty základní.

Nyní si pojďme ukázat, jak například změnit první znak a mezi každým písmenem vypsat mezeru:

string pozdrav = "Hello World!";
pozdrav[0] = 'h';
for (int i = 0; i < 12; i++ )
    cout << pozdrav[i] << ' ';
cout << endl;
cin.get();

Výsledek:

Konzolová aplikace
h e l l o   W o r l d !

Změnou prvního znaku na 'h' jsme zmenšili první písmeno textu. Díky hranatým závorkám jsme poté mohli k řetězci přistoupit jako k poli a vypsat jednotlivé znaky oddělené mezerou.

Čtení/výpis řetězce

Řetězce můžeme jednoduše načítat/vypisovat jako jsme byli zvyklí doposud, použijeme k tomu objekt cin. Proměnnou pro řetězec založíme jako typ string.

Následující program si nechá zadat vaše jméno a poté vás pozdraví:

string jmeno;
cout << "Zadejte vase jmeno: ";
cin >> jmeno;
cout << "Zdravim " << jmeno << endl;
cin.ignore(0xFF,'\n');
cin.get();

Výsledek nás možná překvapí:

Konzolová aplikace
Zadejte vase jmeno: David Capka
Zdravim David

Všimněme si, že bylo načteno pouze první slovo. Při vstupu pomocí cin se čtení ukončí na prvním tzv. bílém znaku. To jsou znaky, které nelze vytisknout, jako např. mezera, enter nebo tabulátor. Také si všimněme řádky cin.ignore(0xFF,'\n'). Ta udává, že všechen text, který ještě na vstupu čeká, se má ignorovat, a to až po znak '\n', který označuje enter. Pokud bychom tuto metodu nezavolali, cin.get() by automaticky přečetl další znak, který by byl ve frontě a program by se ihned ukončil.

Pokud bychom chtěli přečíst celý řádek, využijeme k tomu funkci getline(), která jako první parametr přijímá objekt cin a jako druhý řetězec, do kterého text uloží.

string jmeno;
cout << "Zadejte vase jmeno: ";
getline(cin, jmeno);
cout << "Zdravim " << jmeno << endl;
cin.get();

Standardní funkce pro práci s řetězci

Typ string nám poskytuje mnoho připravených funkcí pro práci s řetězci, které zjednoduší naše programy.

length() - délka řetězce

Délku řetězce můžeme zjistit pomocí metody length() (podrobnější popis rozdílu mezi metodou a funkcí je opět součástí kurzu OOP).

string pozdrav = "Hello World";
unsigned int delka = pozdrav.length();
cout << delka;

clear() - smazání řetězce

Pokud chceme uvolnit místo, použijeme metodu clear(). Ta smaže všechen obsah, který je v proměnné uložen.

string pozdrav = "Hello World";
pozdrav.clear();

Spojení řetězců

2 textové řetězce můžeme spojit do jednoho pomocí operace +, jak jsme zvyklí například u aritmetických operací.

string prvniPozdrav = "Hello ";
string druhyPozdrav = "World";
string pozdrav = prvniPozdrav + druhyPozdrav;
cout << pozdrav;

find() - vyhledání podřetězce

V textu si můžeme nechat vyhledat nějaký znak nebo řetězec. C++ ho od začátku do konce prohledá a pokud znak nebo řetězec nalezne, vrátí jeho pozici. Pokud řetězec znak neobsahuje, vrátí metoda hodnotu větší, než je poslední index řetězce.

string text = "Pan X znovu udeřil.";
unsigned int pozice = text.find("ovu");
if (pozice < text.length())
    cout << "Nalezeno na pozici " << pozice << endl;
else
    cout << "Nenalezeno" << endl;
cin.get();

Asi vás nepřekvapí, že se pozice indexuje od nuly.

Konzolová aplikace
Nalezeno na pozici 8

Dále string poskytuje sadu obdobných metod, pouze s jinou funkcionalitou:

  • rfind(): najde poslední výskyt
  • find_first_of(): najde první výskyt libovolného znaku z parametru
  • find_last_of(): najde poslední výskyt libovolného znaku z parametru
  • substr(): vrátí podřetězec, určený počátkem a délkou

Porovnání řetězců

Porovná 2 řetězce podle abecedy. Můžeme využít porovnávací operace jako větší (>) a menší (<).

string prvni = "Hello";
string druhy = "World";
bool porovnani= prvni < druhy;
cout << porovnani;

Metody pro práci s řetězci je mnohem více. Podrobně se s nimi seznámíme v jednom z dalších článků.

Další interpretace řetězců

C++ poskytuje i podporu pro nízkoúrovňový přístup k řetězcům, tedy umožňuje je kromě stringů definovat i jen jako obyčejná pole typu char. Typ string je v C++ pouze obal, který vnitřně používá právě tento nízkoúrovňový přístup. Budete-li pracovat s knihovnami pro C nebo budete-li volat systémová volání, budete nuceni použít jen charová pole. Tato interpretace je používaná v C (protože C string nemá), a tak vás přesměruji na díl o textových řetězcích v C. Základní popis můžete nalézt v lekci Textové řetězce, téma je dále rozšířeno v lekci Textové řetězce podruhé.

Pro dnešek by to bylo vše. V příští lekci, Textové řetězce v jazyce C++ podruhé - Práce se znaky, se budeme věnovat dále textovým řetězcům a to na několika praktických programech.


 

Stáhnout

Staženo 40x (15.91 kB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

 

Článek pro vás napsal patrik.valkovic
Avatar
Jak se ti líbí článek?
4 hlasů
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Předchozí článek
Pole v C++
Všechny články v sekci
Základní konstrukce jazyka C++
Miniatura
Následující článek
Textové řetězce v jazyce C++ podruhé - Práce se znaky
Aktivity (16)

 

 

Komentáře
Zobrazit starší komentáře (6)

Avatar
Elektron
Člen
Avatar
Elektron:22.10.2017 19:35

Raději používej Code Blocks než VS.

 
Odpovědět  +1 22.10.2017 19:35
Avatar
Odpovídá na Elektron
Jaroslav Dubánek:23.10.2017 18:01

Už jsem na něj přešel. Máš pravdu, je to lepší.

Odpovědět 23.10.2017 18:01
Život je ve skutečnosti strašně jednoduchej.
Avatar
Miroslav Jaroš:18.11.2018 18:03

Pohral som sa s find() a nieco mi nesedi. Ak pouzijem taketo nieco :

int pozicia = text.find("x");

a znak x mi v stringu text nenajde tak hodnota nie je vyssia ako hodnota posledneho indexu, ale -1. Nechal som si to vypisat do konzoly.
Vrtal som sa v tom, lebo to porovnavanie

if (pozicia < text.length())

mi vo VS sposobovalo varovanie:
Warning C4018 '<': signed/unsigned mismatch
Program, ale napriek tomu fungoval spravne. Aj ked -1 je vlastne mensie, program ho v tej podmienke bral ako vacsie.
To koli tomu, ze porovnavam signed(int) a unsigned(length())? Preto mi dalo, ze -1 je vacsie ako kladne cislo?
Je logicke, ze length() vrati vzdy unsigned,kedze zaporna dlzka nemoze byt, tak ani nie je dovod tam davat taky datovy typ.
Je dobre to takto pouzivat ked dostavam od VS varovanie a spravne by ta podmienka nemala byt splnena? Uvazoval som, ze to pretypujem, ale kdze to funguje, nechal som to tak.
Dakujem.

 
Odpovědět 18.11.2018 18:03
Avatar
Odpovídá na Miroslav Jaroš
Miroslav Jaroš:18.11.2018 18:10

Len chcem este doplnit, ak to bolo nezrozumitelne, ze ak je ta pozicia -1, cize znak x nenaslo, tak to if, co som pisal, neprebehne a pokracuje na else. Aj ked logicky by malo prebehnut to co je v if(-1 je mensie ako dlzka toho textu).

 
Odpovědět 18.11.2018 18:10
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Miroslav Jaroš
patrik.valkovic:18.11.2018 19:18

Při porovnávání unsigned int a int se int automaticky přetypuje na unsigned. -1 je pro unsigned roven nejvyšší hodně, jakou může unsigned int nabývat. text.length() vrací unsigned, proto program funguje. Je pravda, že správně by měla být proměnná pozicia být typu unsigned int. Warning ve VS je správný.

Odpovědět 18.11.2018 19:18
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Miroslav Jaroš:18.11.2018 19:32

V clanku je teda chyba: "Pokud řetězec znak neobsahuje, vrátí metoda hodnotu větší, než je poslední index řetězce.".

 
Odpovědět 18.11.2018 19:32
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Miroslav Jaroš
patrik.valkovic:18.11.2018 20:11

Proč? Hodnota nikde nadefinovaná neni, pouze je zaručeno že je větší než je délka řetězce.

Odpovědět 18.11.2018 20:11
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Miroslav Jaroš:18.11.2018 20:41

Mne to vracia -1, cize je mensia. Funguje to len vdaka pretypovaniu co spravilo koli tomu signed/unsigned mismatch , ale ak by som to chcel pouzit inak(napr. ak by som sa chcel zbavit toho varovania vo VS), tak ta info nie je spravna. Ak by som to porovnal s unsigned typom tak nie je zarucene, ze je vecsia.
Alebo som nieco nepochopil? Snazim sa to len co najlepsie pochopit a teraz som sa v tom este viac zamotal ked nesuhlasis s mojim tvrdenim, ze je tam chyba. :)
Podla clanku ta metoda vrati hodnotu vacsiu ako je posledny index a nie, ze v tomto konkretnom pripade co je spomenuty sa v tej podmienke zmeni na vacsiu vdaka pretypovaniu koli nepsravnemu porovnaniu rozdielnych typov.
Nechcem teraz silou mocou trvat na svojom a chapem, ze ja som ten co toho vie v tomto pripade menej, len sa to ucim, ale ozaj sa snazim pochopit co najviac a v tomto pripade mi to vobec nesedi. -1 predsa nemoze byt vacsie ako posledny index v retazci.

 
Odpovědět 18.11.2018 20:41
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Miroslav Jaroš
patrik.valkovic:18.11.2018 21:13

Metoda find i size vrací size_t, tedy unsigned int. Rovná se to -1, protože jsi výsledek uložil do hodnoty int, ne unsigned int. Pokus ji uložíš to unsigned int (jak by to mělo být správně), potom bude hodnota větší.

Editováno 18.11.2018 21:13
Odpovědět  +1 18.11.2018 21:13
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovídá na patrik.valkovic
Miroslav Jaroš:18.11.2018 21:18

Vdaka, uz mi je to jasne :) ... Mozno by sa to malo doplnit do clanku. Sorac ak som moc otravoval, ale toto je moj 3 pokus naucit sa programovat a strasne chcem aby bol aj posledny a uspesny :) ... Do vsetkeho chcem vrtat kym to nepochopim na 100% :)

 
Odpovědět 18.11.2018 21:18
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 16. Zobrazit vše