9. cvičení

Třída string pro práci s textovými řetězci

Pro práci s textovými řetězci je ve standardní knihovně k dispozici třída std::string. Abychom mohli string použít, musíme includovat správný hlavičkový soubor:

#include <string>
using namespace std;

Poté můžeme s třídou string pracovat v některých ohledech stejně, jako se základními číselnými typy. Např. vytvoření prázdné proměnné, nastavení textového řetězce a výpis lze zapsat pomocí stejných operátorů:

string s;
s = "Hello, world!";
cout << s << endl;

Zadání textu z terminálu lze provést obdobně pomocí objektu cin a operátoru >>:

cout << "zadej text: ";
cin >> s;

Tento operátor však přečte nejvýše jedno slovo (pro oddělení se použijí tzv. bílé znaky). Pokud chceme přečíst více, musíme použít buď operátor >> v cyklu, nebo nějaký jiný způsob načítání. K dispozici je ještě např. funkce getline, která přečte celý řádek:

getline(cin, s);

Třída string také funguje podobně, jako pole, takže pro přístup k jednotlivým znakům můžeme použít operátor hranaté závorky ([]). Aktuální počet znaků, čili velikost textového řetězce, můžeme získat pomocí metody length nebo size:

for (int i = 0; i < s.size(); i++) {
    cout << i << "-ty znak je " << s[i] << endl;
}

K dispozici je i mnoho dalších metod, jejichž seznam naleznete v online dokumentaci. Samozřejmě není třeba učit se seznam nazpaměť, ale je dobré mít přehled o tom, jaké metody jsou obecně k dispozici, a umět si dohledat jejich použití, když potřebujete něco naprogramovat.

Příklad: funkce pro počítání slov v textovém řetězci

Funkci pro počítání slov oddělených mezerami v textovém řetězci můžeme naprogramovat několika způsoby. Můžeme např. přeskočit všechny mezery na začátku, zvýšit čítací proměnnou o 1, přeskočit všechny nemezery (tj. najít další mezeru), a celý tento postup opakovat, dokud nedojdeme na konec řetězce.

int pocet_slov(string text)
{
    int pocet = 0;

    for (int i = 0; i < text.size(); i++) {
        // preskocit mezery
        while (text[i] == ' ' && i < text.size())
            i++;

        // zvysit pocet
        if (i < text.size())
            pocet++;

        // preskocit nemezery
        while (text[i] != ' ' && i < text.size())
            i++;
    }

    return pocet;
}

Alternativně můžeme spočítat všechny dvojice znaků, kde první je mezera a druhý není mezera.

int pocet_slov(string text)
{
    int pocet = 0;

    // pokud prvni znak neni mezera, zacneme pocitat od 1
    if (text[0] != ' ') {
        pocet = 1;
    }

    for (int i = 1; i < text.size(); i++) {
        if (text[i-1] == ' ' && text[i] != ' ') {
            pocet++;
        }
    }

    return pocet;
}

Pro větší obecnost můžeme použít funkci isspace ze standardní knihovny, která porovnává svůj argument se všemi bílými znaky v ASCII tabulce (nejen se znakem ' '). Tato funkce je dostupná v hlavičkovém souboru cctype (jsou zde i další funkce užitečné pro porovnávání znaků). V příkladu výše bychom tedy místo text[i] == ' ' psali isspace(text[i]) apod.