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í.

4. diel - Reťazca v Qt - QString a QChar

V minulej lekcii, Dokončenie prvého okna v Qt a C ++ - Tlačidlo , sme sa posunuli v obsasti formulárových aplikácií v Qt a C ++ o poriadny krok ďalej. Uviedli sme si problematiku layout manažérov, vložili na formulár prvý komponent a naučili sa aj obsluhovať signály pomocou slotov. Než sa pustíme do ďalších okenných aplikácií, bude dobré si povedať niečo málo o triede QString, ktorá obsahuje veľmi výkonné metódy a nie je ich práve málo.

QString

Táto trieda je schopná pracovať s unicode reťazcami, ktoré kóduje do 16-tich bitových znakov. Práve s kódovaním textu má inak C ++ problém, na čo ste vďaka tomu, že v slovenčine používame háčiky a čiarky, asi už prišli. Pre tento účel využíva QString triedu QChar a texty ukladá ako pole QChar[].

Predovšetkým je celkom pozitívne, že QString je, na rozdiel od reťazcov mnohých programovacích jazykov, mutable - teda obsah objektu môžeme ľubovoľne meniť, napr. Meniť písmená v texte. Tiež by som si dovolil trochu sa odchýliť od C ++ knižnice iostream. Pretože sa rozprávame o Qt frameworku, budeme dnes namiesto neho používať textový prúd na štandardný výstup pomocou triedy QTextStream.

A mimo to, iostream nedokáže pracovať s Qt reťazcami. Tuším, že unicode zvláda pomocou ukazovateľa na typ wchar_t. Sami si to môžete overiť na tomto malom experimentu:

#include <iostream>
#include <QString>

using namespace std;

int main(int argc, char *argv[])
{
    QString text = QString("Ahoj světe! Jak se máš?");

    cout << text << endl;
}

Ak sa tento zdrojový kód pokúsite preložiť, vypadne vám nasledujúce chyba:

Konzolová aplikácia
Chyba: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘QString’)
cout << text << endl;
~~~~~^~~~~~~

Vytvorenie projektu

Poďme sa pozrieť na niekoľko prvých možností. Vytvoríme si v QtCreatoru konzolový projekt, napr. S názvom retezce. Súbor main.cpp upravíme do podoby nižšie. Potom si podrobne prejdeme jednotlivé kroky:

#include <QTextStream>
#include <QString>

int main(void) {

    QTextStream out(stdout);

    QString str = "líbí";

    str.append(" ITNetwork!!!");
    str.prepend("Mně se ");

    out << str << endl;
    out << "Retezec obsahuje " << str.count() << " znaku" << endl;

    out << str.toUpper() << endl;
    out << atr.toLower() << endl;

    return 0;
}

Nastavíme znakový prúd na štandardný výstup, teda terminál / konzolu. Ďalej sa objekt out chová veľmi podobne ako knižnica iostream.

Ďalej vytvoríme QString premennú str a inicializujeme ju nejakým reťazcom: QString str = "líbí". Existuje vice možností inicializácia, napr. Aj QString str("líbí").

Pretože som tvrdil, že tieto reťazce sú modifikovateľné, treba to hneď skúsiť. Za pôvodný obsah str pridáme nejaký ďalší text pomocou a.append(" ITNetwork!!!") a aby sme si predviedli silu QString, tak skúsime pridať aj pred neho nejaký text ako a.prepend("Mě se ");.

Výsledok pošleme na terminál a odřádkujeme: out << str << endl;

Ďalší riadok bude chcieť viac slov. Chceli sme zistiť, koľko má reťazec znakov. Vhodná metóda na tento účel je str.count(). Tiež je možné použiť aj jej ekvivalenty str.length() a str.size(), záleží na vašom zvyku a čo si zapamätáte lepšie.

Všimnite si, že výpis neobsahuje diakritiku a ani nemôže, pretože bežný reťazec odoslaný na textový prúd je vlastne ukazovateľ na pole typu char a nie QChar.

V posledných dvoch riadkoch len znaky reťazca prevedieme na veľké písmená pomocou out << str.toUpper() << endl a na malé ako out << atr.toLower() << endl. Tu by som chcel upozorniť, že tieto dve metódy nevracia zmenený reťazec, ale jeho zmenenou kópiu. Pôvodný obsah sa zachováva. A výsledok by mal vyzerať nejako takto:

Konzolová aplikácia
Mně se líbí ITNetwork!!!
Retezec obsahuje 23 znaku
MNĚ SE LÍBÍ ITNETWORK
mně se líbí itnetwork
Zavřete toto okno...

Ako bolo vyššie povedané, texty sa vnútorne ukladajú ako pole QChar a teda aj takto je možné k dátam pristupovať. Skúsme si pridať tieto dva riadky, ktoré vypíšu znak na danej pozícii (snáď nemusím upozorňovať, že pred return 0):

out << str[0] << endl;     // M
out << str[4] << endl;     // !

Samozrejme, existuje aj metóda str.at(n), kde n je pozícia znaku v reťazci počítaná od 0 do str.size() - 1.

Argumenty reťazcov

Ďalším pozitívom QString je, že reťazce môžu mať argumenty. Ak chceme napr. Vypísať text: "Na louce se prohání 15 koní.", To by problém nebol. Ale čo keď sa jeden kôň zabehne do lesa. To ich na lúke máme už len 14. Nechcelo by to nejakú variabilná možnosť, ako ich počet do reťazca vložiť, než takto "na pevno"? Práve k tomu nám slúži metóda str.arg(var), ktorá funguje podobne ako napr. printf() v jazyku C.

Pridáme si ďalšie riadky na ukážku:

QString kone("Na louce se prohání %1 koňů.");
int louka = 15;
out << kone.arg(louka) << endl;

Ďalšie argumenty sa môžu zreťazovať rovnakou metódou arg(var1).arg(var2)...:

QString kone2("Na louce se prohání %1 koňý a %2 je (jsou) v lese.");
louka = 12;
int les = 3;
out << kone2.arg(louka).arg(les) << endl;

Výsledok na termináli je podobný tomuto:

Konzolová aplikácia
MNĚ SE LÍBÍ ITNETWORK
mně se líbí itnetwork
M
!
I
Na louce se prohání 15 koňů.
Na louce se prohání 12 koňý a 3 je (jsou) v lese.
Zavřete toto okno...

Ak si prajete použiť iný typ argumentu ako integer, nie je to problém. Dokonca na rovnaký reťazec môžete použiť akýkoľvek typ. Pravda, všetky som nikdy neskúšal:

QString kone3("Kobyla má %1 hříbat a valach má %2 kobyl:-D.");
int hribe = 1;
double kobyla = 0.01;
out << kone3.arg(hribe).arg(kobyla) << endl;

A výsledok:

Konzolová aplikácia
Na louce se prohání 15 koňů.
Na louce se prohání 12 koňý a 3 je (jsou) v lese.
Kobyla má 1 hříbat a valach má 0.01 kobyl:-D.
Zavřete toto okno...

Práca s podreťazci

Premažeme naše ukážky až na základ a porozprávame sa o ďalších metódach triedy QString, určite sa vám budú páčiť - vyberajú podreťazca. Keď som kedysi začínal programovať na ZX Spectra, tak práve tieto funkcie mi dosť chýbali ... aj keď ich bolo možné nahradiť inou konštrukciou. Sú to metódy:

  • left(n) - vráti n znakov zľava,
  • right(n) - vráti n znakov sprava,
  • mid(n, m) - vráti m znakov od pozície n.

Prosím, pamätajte, že pozícia sa číslujú od nuly.

Skúsme si opäť nejaký príklad:

#include <QTextStream>
#include <QString>

int main(void) {
    QString str("Jsme ve vesmíru jediní?");

    out << str.left(4) << endl;
    out << str.right(7) << endl;
    out << str.mid(8,7) << endl;

    return 0;

výsledok:

Konzolová aplikácia
Jsme
jediní?
vesmíru
Zavřete toto okno...

Zistenie druhu znaku

Dosť často sa môže hodiť rozhodnutie, či znak v reťazci je písmeno, číslo, biely znak alebo niečo úplne iné. Môžeme si skúsiť urobiť malú analýzu textu. Qt k tomu ponúka mnoho nástrojov. Napr. už len to, že celý text je iterovatelný v cykle, že je k dispozícii prístup k jednotlivým znakom a že pre znaky sú metódy, ktoré vedia rozhodnúť aký typ znaku to je. V základe ide o metódy isLetter() pre písmená, isDigit() pre číslice, isSpace() pre biele znaky a isPunct() pre interpunkciu, teda bodky, čiarky, výkričníky a tak podobne.

Myslím, že najlepšie bude si to hneď vyskúšať. Budeme analyzovať jednoduchú vetu a zisťovať počty rôznych druhov znakov:

#include <QTextStream>
#include <QString>          // Není nutné, ale zvyk je zvyk
#include <QChar>            // Jako o řádek výše
int main(void) {

    QTextStream out(stdout);

    int pismena  = 0;
    int cisla = 0;
    int mezery  = 0;
    int intpunk  = 0;

    QString str = "Na louce se pase 1 bílý\tkůň.\n";


    // Iterace nad řetězcem
    foreach(QChar s, str) {

        if (s.isDigit()) {
            cisla++;
        }
        else if (s.isLetter()) {
            pismena++;
        }
        else if (s.isSpace()) {
            mezery++;
        }
        else if (s.isPunct()) {
            intpunk++;
        }
    }

    // Výsledek vypíšeme
    out << QString("Máme celkem %1 znaků").arg(str.count()) << endl;
    out << QString("Z toho je %1 písmen").arg(pismena) << endl;
    out << QString("pak je tam %1 čísel").arg(cisla) << endl;
    out << QString("krom toho i %1 mezer").arg(mezery) << endl;
    out << QString("a %1 znaků interpunkce").arg(intpunk) << endl;

    return 0;
}

Myslím, že tu ani nie je nutné toho veľa vysvetľovať. Snáď len onen cyklus foreach nad QString. Proste každý znak je QChar, ktorý sa postupne ukladá do premennej s, kým sa nenarazí na koniec textu. Po spustení by sa mohla zobraziť podobná správa ako nižšie na obrázku:

Konzolová aplikácia
Máme celkem 29 znaků
Z toho je 20 písmen
pak je tam 1 čísel
krom toho i 7 mezer
a 1 znaků interpunkce
Zavřete toto okno...

No aby toho nebolo naraz až príliš, tak dnešné rozprávanie by som ukončil a nabudúce ešte na túto tému nadviazal. Reťazce sa používajú veľmi často a preto si niečo povieme o ich zmenách, porovnávanie, doplňovanie a určite si ešte na niečo zaujímavé spomeniem.

Ďakujem za pozoronost a uvidíme sa zas nabudúce v lekcii Jednoduchá kalkulačka v Qt a C ++ - Layout .


 

Predchádzajúci článok
Dokončenie prvého okna v Qt a C ++ - Tlačidlo
Všetky články v sekcii
Qt - Okenné / formulárové aplikácie v C ++
Preskočiť článok
(neodporúčame)
Jednoduchá kalkulačka v Qt a C ++ - Layout
Článok pre vás napísal Virlupus
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje webovým aplikacím, skladově-účetnímu softwaru, 3D grafice, lexiální analýze a parserování. Studuje fyziku na MFF UK. Učil IT na střední škole.
Aktivity