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átin
znakov zľava,right(n)
- vrátin
znakov sprava,mid(n, m)
- vrátim
znakov od pozícien
.
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 .