Lekce 4 - Typový systém podruhé - datové typy
V předešlém cvičení, Řešené úlohy k 1.-3. lekci Dartu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V minulé lekci Dart kurzu, Řešené úlohy k 1.-3. lekci Dartu, jsme si ukázali základní datové
typy. Byly to int
, String
a double
. Nyní
se na datové typy podíváme více zblízka a vysvětlíme si, kdy jaký
použít. Dnešní lekce bude hodně teoretická, ale o to více bude praktická
ta příští. Na konci si vytvoříme pár jednoduchých ukázek.
Většina programovacích jazyků rozeznává 2 druhy datových typů a to hodnotové a referenční. Vše v Dartu je tzv. objekt s čímž ruku v ruce jde to, že typy v Dartu jsou referenční. K referenčním typům se dostaneme podrobněji až u objektově orientovaného programování, kde si také všechno do podrobna vysvětlíme.
Datové typy Dartu
Dart má podporu pro několik datových typů: čísla, řetězce, logické hodnoty, seznamy, mapy, runy a symboly. Posledními 3 se nebudeme v tomto prvním kurzu zabývat.
Čísla
V Dartu rozlišujeme 2 typy čísel, a to sice čísla celá
a desetinná. Pro celá čísla se používá datový typ
int
, pro desetinná čísla datový typ double
. Typy
int
i double
jsou podtypy typu num
.
V rámci typu num
jsou definovány základní operátory
+
, -
, /
a *
a taktéž
základní metody jako abs()
, ceil()
,
floor()
a mnoho dalších. Bitové operátory, jako například
bitový posun vpravo >>
, jsou definovány v rámci typu
int
. Další matematické metody můžete najít i v knihovně
dart:math
.
I přes to, že Dart (Dart VM) podporuje libovolnou přesnost celých čísel, čísla by měla být v rozsahu -253 až 253, zejména pokud používáte Dart v prohlížeči, kde platí omezení Javascriptu.
Desetinná čísla jsou reprezentována jako 64bitová čísla s dvojitou přesností, jak je specifikováno ve standardu IEEE 754.
int a = 5; double b = 3.14; num c = 6; num d = 12.8
Logická hodnota
Pro logické hodnoty se používá datový typ bool
a může
nabývat dvou hodnot: true
(pravda) nebo false
(nepravda). Budeme ho používat zejména tehdy, až se dostaneme k podmínkám.
Do proměnné typu bool
lze uložit jak přímo hodnotu
true
/false
, tak i logický výraz. Zkusme si
jednoduchý příklad:
bool b = false; bool vyraz = 15 > 5; print(b); print(vyraz);
Výstup programu:
Konzolová aplikace
false
true
Vidíme, že výraz nabývá hodnoty true
(pravda), protože
15
je opravdu větší než 5
. Od výrazů je to jen
krok k podmínkám, na ně se podíváme příště.
Řetězce
Pro řetězce v Dartu se používá datový typ String
a jsou to
sekvence znaků v UTF-16. Pro řetězce můžete použít
apostrofy i uvozovky, obě možnosti jsou v Dartu ekvivalentní.
print('Vítám tě, čtenáři!'); print("Dart je skvělý jazyk."); print('A ty\'s skvělým čtenářem ITnetwork.'); print("Život je prostě \"ňuňu\".");
Kromě toho v Dartu existují i víceřádkové řetězce, které se označují trojitými apostrofy nebo uvozovkami. Pozor si lze musíme dávat na mezery na začátcích řádků a odřádkování před/po trojitým apostrofem/uvozovce.
print(''' Jsem na více řádek!'''); print(""" Tady mi pak nějaká "uvozovka" v uvozovce nikde už nevadí. """);
Výstup v konzoli pak bude vypadat nějak takto:
Konzolová aplikace
Vítám tě, čtenáři!
Dart je skvělý jazyk.
A ty's skvělým čtenářem ITnetwork.
Život je prostě "ňuňu".
Jsem na
více
řádek!
Tady mi pak
jedna "uvozovka" nikde už nevadí.
String
má na sobě řadu opravdu užitečných metod. Některé
si teď probereme a vyzkoušíme:
startsWith(), endsWith() a contains()
Můžeme se jednoduše zeptat, zda řetězec začíná, končí nebo zda
obsahuje určitý podřetězec (substring). Podřetězcem myslíme část
původního řetězce. Všechny tyto metody budou jako parametr brát
samozřejmě podřetězec a vracet hodnoty typu bool
(true
/false
). Zatím na výstup neumíme reagovat, ale
pojďme si ho alespoň vypsat:
String s = 'Krokonosohroch'; print(s.startsWith('krok')); print(s.endsWith('hroch')); print(s.contains('nos')); print(s.contains('roh'));
Výstup programu:
Konzolová aplikace
false
true
true
false
Vidíme, že vše funguje podle očekávání. První výraz samozřejmě neprošel díky tomu, že řetězec ve skutečnosti začíná velkým písmenem.
toUpperCase() a toLowerCase()
Rozlišování velkých a malých písmen může být někdy na obtíž.
Mnohdy se budeme potřebovat zeptat na přítomnost podřetězce tak, aby
nezáleželo na velikosti písmen. Situaci můžeme vyřešit pomocí metod
toUpperCase()
a toLowerCase()
, které vrací řetězec
ve velkých a v malých písmenech. Uveďme si reálnější příklad než je
Krokonosohroch. Budeme mít v proměnné řádek konfiguračního souboru,
který psal uživatel. Jelikož se na vstupy od uživatelů nelze spolehnout,
musíme se snažit eliminovat možné chyby, zde např. s velkými písmeny.
String konfig = 'Fullscreen shaDows autosave'; konfig = konfig.toLowerCase(); print('Poběží hra ve fullscreenu?'); print(konfig.contains('fullscreen')); print('Budou zapnuté stíny?'); print(konfig.contains('shadows')); print('Přeje si hráč vypnout zvuk?'); print(konfig.contains('nosound')); print('Přeje si hráč hru automaticky ukládat?'); print(konfig.contains('autosave'));
Výstup programu:
Konzolová aplikace
Poběží hra ve fullscreenu?
true
Budou zapnuté stíny?
true
Přeje si hráč vypnout zvuk?
false
Přeje si hráč hru automaticky ukládat?
true
Vidíme, že jsme schopni zjistit přítomnost jednotlivých slov v řetězci tak, že si nejprve řetězec převedeme celý na malá písmena (nebo na velká) a potom kontrolujeme přítomnost slova jen malými (nebo velkými) písmeny. Takhle by mimochodem mohlo opravdu vypadat jednoduché zpracování nějakého konfiguračního skriptu.
trim(), trimLeft() a trimRight()
Problémem ve vstupech od uživatele může být i diakritika, ale Dart naštěstí pracuje plně v UTF-16. Nestane se nám tedy, že by se diakritika nějak zkomolila. Další nástrahou mohou být mezery a obecně všechny tzv. bílé znaky, které nejsou vidět, ale mohou nám uškodit. Obecně může být dobré trimovat všechny vstupy od uživatele, můžeme trimovat buď celý řetězec nebo jen bílé znaky před ním a za ním. Prozradím, že při parsovacích funkcích Dart trimuje zadaný řetězec automaticky, než s ním začne pracovat. Zkuste si v následující aplikaci před číslo a za číslo zadat několik mezer:
print('Zadejte číslo:'); String s = stdin.readLineSync(encoding: UTF8); print('Zadal jste text: "$s"'); print('Text po funkci trim: "${s.trim()}"'); int a = int.parse(s); print('Převedl jsem zadaný text na číslo parsováním, zadal jste: $a');
replaceAll()
Asi nejdůležitější metodou na stringu je nahrazení určité jeho
části jiným textem. Jako parametry zadáme dva podřetězce, jeden co chceme
nahrazovat a druhý ten, kterým to chceme nahradit. Metoda vrátí nový
string
, ve kterém proběhlo nahrazení. Když daný podřetězec
metoda nenajde, vrátí původní řetězec. Zkusme si to:
String s = "Java je nejlepší!"; s = s.replaceAll("Java", "Dart"); print(s);
Výstup programu:
Konzolová aplikace
Dart je nejlepší!
padLeft() a padRight()
Jako poslední si zmíníme metody, které nám k textu naopak mezery
přidají. K čemu to je
dobré? Představte si, že máme 100 proměnných a budeme je chtít
uspořádat do tabulky. Text upravíme pomocí metody
padRight()
s
parametrem šířky sloupce, tedy např. 20 znaků. Pokud bude mít text jen 12
znaků, vypíše se před něj 8 mezer, aby měl velikost 20. Obdobně metoda
padLeft()
by vypsala 8 mezer za něj. Jelikož nemáme znalosti k
vytvoření takové tabulky, budeme si metody jen pamatovat a vyzkoušíme si je
dále v seriálu.
length
Poslední, ale nejdůležitější vlastnost (pozor, ne metoda) je
length
, tedy délka. Vrací celé číslo, které představuje
počet znaků v řetězci. Za vlastnosti nepíšeme závorky, protože nemají
parametry.
print('Zadejte vaše jméno:'); String jmeno = stdin.readLineSync(encoding: UTF8); print('Délka vašeho jména je: ${jmeno.length}');
Je toho ještě spoustu k vysvětlování a jsou další datové typy, které
jsme neprobrali. Abychom však stále neprobírali jen teorii, ukážeme si již
v příští lekci, Řešené úlohy k 4. lekci Dartu, podmínky a později cykly. Potom bude naše
programátorská výbava dostatečně velká k tomu, abychom tvořili zajímavé
programy.
V následujícím cvičení, Řešené úlohy k 4. lekci Dartu, si procvičíme nabyté zkušenosti z předchozích lekcí.