Java týden Předvánoční slevová akce
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde
Pouze tento týden sleva až 80 % na Java e-learning!

Lekce 3 - Typový systém podruhé: Datové typy ve Swift

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 Swift kurzu, Proměnné, typový systém a parsování ve Swift, 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.

Swift rozeznává dva druhy datových typů, hodnotové a referenční. Těm referenčním se budeme věnovat později.

Hodnotové datové typy

Proměnné hodnotového datového typu si dokážeme jednoduše představit. Může se jednat např. o číslo nebo znak. V paměti je jednoduše uložena přímo hodnota a my k této hodnotě můžeme z programu přímo přistupovat. Slovo přímo jsem tolikrát nepoužil jen náhodou. V tomto Swift kurzu se budeme věnovat výhradně těmto proměnným.

Celočíselné datové typy

Podívejme se nyní na tabulku všech vestavěných celočíselných datových typů ve Swift, všimněte si typu Int, který již známe z minula.

Datový typ Rozsah Velikost
Int -2 147 483 648 až 2 147 483 647 32 bitů
UInt 0 až 4 294 967 295 32 bitů

Rozsahy těchto typů si samozřejmě nemusíte pamatovat, pro celá čísla můžete jednoduše používat vždy typ Int.

Více informací můžete nalézt v oficiální dokumentaci. Tu otevřete skrze Help -> Developer Documentation. Pak už stačí jen vyhledávat. Ke konkrétním datovým typům apod. se můžete snadno dostat skrze Quick Help inspektor v pravé straně Xcode. Stačí mít označený např. Int typ a v inspektoru kliknout na Structure Reference.

Prefix "U" u UInt znamená, že neumožňuje uložit zápornou hodnotu a tím pádem může uložit dvojnásobnou kladnou. Těmto typům se říká unsigned, klasickým signed.

Desetinná čísla

U desetinných čísel je situace podobná, máme na výběr dva datové typy. Samozřejmě se liší opět v rozsahu hodnoty, dále však ještě v přesnosti (vlastně počtu des. míst). Typ Double má již dle názvu dvojnásobnou přesnost oproti Float.

Datový typ Rozsah Přesnost
Float +-1.5 * 10−45 až +-3.4 * 1038 7 čísel
Double +-5.0 * 10−324 až +-1.7 * 10308 15-16 čísel

Vzhledem k tomu, že desetinná čísla jsou v počítači uložena ve dvojkové soustavě, dochází k určité ztrátě přesnosti. Odchylka je sice téměř zanedbatelná, nicméně když budete programovat např. finanční systém, nepoužívejte tyto dat. typy pro uchování peněz, mohlo by dojít k malým odchylkám.

Typ Double je pro desetinná čísla výchozí, Float je tak nutné blíže specifikovat.

let f : Float = 3.14
let d = 2.72

Jako desetinný separátor používáme ve zdrojovém kódu vždy tečku, nehledě na to, jaké máme v macOS regionální nastavení.

Další vestavěné datové typy

Podívejme se na další datové typy, které nám Swift nabízí:

Datový typ Rozsah Velikost/Přesnost
Character U+0000 až U+ffff 16 bitů
Decimal +-1.0 * 10−28 až +-7.9 * 1028 28-29 čísel
Bool true nebo false 8 bitů

Character

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Character nám reprezentuje jeden znak, na rozdíl od Stringu, který reprezentoval celý řetězec Characterů. Znaky v Swift píšeme do klasických uvozovek a datový typ je nutné specifikovat, jinak bude použit String:

let c : Character = "A"

Decimal

Typ Decimal řeší problém ukládání desetinných čísel v binární podobě, ukládá totiž číslo vnitřně podobně jako text. Používá se tedy pro uchování peněžních hodnot. Ke všem dalším matematickým operacím s des. čísly použijeme Double nebo Float. K zápisu Decimal hodnoty opět musíme datový typ specifikovat:

let number : Decimal = 3.14159265358979323846

Bool

Datový typ Bool nabývá dvou hodnot: true (pravda) a 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:

let b = false
let vyraz = 15 > 5
print(b)
print(vyraz)

Výstup programu:

false
true

Výrazy můžeme psát do závorek. To se hodí v případě, že jich máme např. několik. 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ě.

String

Datový typ, se kterým se setkáte na každém kroku. Reprezentuje řetězec znaků, či prostě jakýkoliv text. Jedná se o hodnotový typ. My si ukážeme hlavně důležité metody, které je dobré znát nebo alespoň vědět, že existují. Metody zkoušejte v Command Line, ne v Playground.

contains(), hasSuffix() a hasPreffix()

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:

let s = "Krokonosohroch"
print(s.hasPrefix("krok"))
print(s.hasSuffix("hroch"))
print(s.contains("nos"))
print(s.contains("roh"))

Výstup programu:

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.

uppercased() a lowercased()

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 uppercased() a lowercased(), 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.

var konfig = "Fullscreen shaDows autosave"
konfig = konfig.lowercased()
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:

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.

trimmingCharac­ters()

Problémem ve vstupech od uživatele může být i diakritika. Swift ale naštěstí pracuje plně v Unicode, 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é tzv. trimovat všechny vstupy od uživatele. Máme dostupnou metodu trimmingCharacters(in: ), přičemž je ještě nutné zadat, co budeme trimovat, protože se jedná o výčet, tak napíšeme . a Xcode nám samo navrhne hromadu možností, co trimmovat. Nejčastěji budete používat možnost .whitespacesAndNewlines, což odstraní všechny bílé znaky a také odřádkování okolo řetězce.

print("Zadejte číslo:")
let s = readLine()!
print("Zadal jste text: " + s)
print("Text po funkci trim: " + s.trimmingCharacters(in: .whitespacesAndNewlines))
let a = Int(s)!
print("Převedl jsem zadaný text na číslo parsováním, zadal jste: \(a)")

replacingOccu­rrences()

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:

let s = "Java je nejlepší!"
let replaced = s.replacingOccurrences(of: "Java", with: "Swift")
print(replaced)

Výstup programu:

Swift je nejlepší!

Iterpolace řetězců

Interpolaci řetězců jsme si již zmiňovali. Ve Swift argumenty či jednoduše proměnné, které chceme do řetězce na určitá místa vložit, zapíšeme přímo do stringu pomocí \():

let a = 10
let b = 20
let c = a + b
let s = "Když sečteme \(a) a \(b), dostaneme \(c)"
print(s)

Výstup programu:

Když sečteme 10 a 20, dostaneme 30

Funkce print() sama umí přijímat text v takovémto formátu, můžeme tedy napsat:

let a = 10
let b = 20
let c = a + b
print("Když sečteme \(a) a \(b), dostaneme \(c)")

Toto je velmi užitečná a přehledná cesta, jak sestavovat řetězce. Pokud chceme vypsat čísla, tak se ji nevyhnete. U více Stringů můžete použít konkatenaci (jednoduše + pro jejich "sečtení").

Vlastnost count

Poslední, ale nejdůležitější vlastnost (pozor, ne metoda) je count, tedy počet znaků. Vrací celé číslo, které představuje počet znaků v řetězci. Za vlastnosti nepíšeme závorky, protože nemají parametry. Slovo "length" by dávalo intuitivně větší smysl, ale Swift vlastnost bere jako zmiňovaný počet znaků, takže si holt musíme zvyknout na count.

print("Zadejte vaše jméno:")
let jmeno = readLine()!
print("Délka vašeho jména je: \(jmeno.count)")

Padding

Padding znamená, že Stringu přidáme znaky, abychom ho dostali na požadovanou délku. Často se používá pro přidání mezer, ale můžete doplnit jakýkoliv znak. Některé jazyky nabízí pohodlné metody pro padding zleva nebo zprava. Swift má pouze jednu a chce po nás celkem dost parametrů. Podrobně si ji popíšeme dále v kurzu.

Pokud vám nějaké metody z této lekce nefungují, ujistěte se, že máte v souboru import Foundation pro importování základní Swift funkcionality.

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, Podmínky (větvení) ve Swift, 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 :)


 

 

Článek pro vás napsal Filip Němeček
Avatar
Jak se ti líbí článek?
4 hlasů
Autor se věnuje vývoji iOS aplikací (občas macOS) či těch webových ve frameworku Django. Twitter: @nemecek_f | GitHub nemecek-filip
Předchozí článek
Proměnné, typový systém a parsování ve Swift
Všechny články v sekci
Základní konstrukce jazyka Swift
Miniatura
Následující článek
Cvičení k 3. lekci Swift
Aktivity (14)

 

 

Komentáře

Avatar
Lukáš Kuchař:1. ledna 17:27

Zdarec, hele není v odstavci trimmingCharac­ters() chybný příklad kódu? Ukázkový kód oproti textu nedává smysl. Popisuješ odstranění bílých znaků, ale v kódu požaduješ zadání čísla, což dle mě nedemonstruje odstranění bílých znaků. Nebo jsem to špatně pochopil?

Editováno 1. ledna 17:27
 
Odpovědět
1. ledna 17:27
Avatar
Filip Němeček
Redaktor
Avatar
Odpovídá na Lukáš Kuchař
Filip Němeček:1. ledna 18:39

Ahoj, tento příklad má sloužit v případě, že uživatel při zadání čísla doplní mezery třeba, takže například zadá: " 3 ". Takže po trimu zbyde pouze 3 a tu lze parsovat do Int.

Kdybych to ukazoval na obyčejném textu typu: "Vítejte na webu ITNetwork", tak výstupem tohoto kódu bude: "Vítejtenawebu­ITNetwork", :-)

 
Odpovědět
1. ledna 18:39
Avatar
Lukáš Kuchař:1. ledna 18:54

OK, díky za info. Teď už tomu rozumím, jak jsi to popsal. Jinak díky za kurz. Vychází sice ze C#, ale chápu, že je zbytečné psát něco dvakrát. Absoloval jsem základní kurz C#, ale jako Apple nadšenec mě vždy zajímal Swift, tak jsem si koupil celý tvůj článek "Základní konstrukce jazyka Swift" a začínám od začátku v jiném jazyce. Klobouk dolů pánové před Vámi. Odvádíte skvělou práci. Díky za Váš web.

 
Odpovědět
1. ledna 18:54
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Sergej Serenatenko:9. ledna 18:54

Ahoj, moc děkuji za pěkný článek. Měl bych ale několik upřesňujících dotazů. a) Má na maximální hodnotu proměnné vliv architektura systému? 32bit vs 64bit? b) Jak je to prosím s Float64 je to prakticky stejný typ jako Double? A na co se používá hodnota Float80? Předpokládám, že má vyšší přesnost něž Float64, Je to jen překvapivé číslo?. :) c) chápu správně, že jestliže je číslo větší než je přesnost dojde k zaokrouhlení nebo oříznutí podle typu proměnné? Předem moc děkuju za odpověď.

Editováno 9. ledna 18:55
 
Odpovědět
9. ledna 18:54
Avatar
Filip Němeček
Redaktor
Avatar
Odpovídá na Sergej Serenatenko
Filip Němeček:12. ledna 11:01

Ahoj, hele upřímně jsem nikdy nepodnikl deep dive do těchto specifičtějších odvětví desetinných čísel. každopádně architektura by neměla mít vliv na max. velikost proměnné, ale spíš na výkon (32bit Float má na 32bit systému stejnou velikost jako pointer a tudíž se s ním rychleji pracuje..) Double je vlastně alias pro Float64 (viz https://developer.apple.com/…wift/float64). Float80 má vyšší přesnost, každopádně jsem o něm do teď nevěděl. c) zde si nejsem jistý natolik, abych odpovídal :-)

 
Odpovědět
12. ledna 11:01
Avatar
Odpovídá na Filip Němeček
Sergej Serenatenko:12. ledna 12:26

Jasný, jsou to okrajové věci, byl jsem jen zvědavý, každopádně moc děkuju za odpověď.

 
Odpovědět
12. ledna 12:26
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 6 zpráv z 6.