Znaky - standardní typ char var Z, W: char; - znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku - v TP (často i jinde) se používá kódová tabulka ASCII 0-31 speciální řídicí znaky 32-127 základní část znakové sady 128-255 národní abecedy resp. semigrafika - dekadické číslice souvislá řada v pořadí od 0 do 9 - velká písmena anglické abecedy souvislá řada od A do Z - malá písmena anglické abecedy souvislá řada od a do z - znakové konstanty lze zapisovat i kódem, např. #65 (totéž co A ) nebo #27 (klávesa Esc) Pavel Töpfer, 2017 Programování 1-7 1
- lze používat v procedurách read, write např. read(z); write( Z ); POZOR v příkladu výše rozlišovat Z a Z! - do proměnné lze dosazovat, např. W:=? ; Z:=W; - na typu char je definováno uspořádání (podle kódů), je možné používat relační operátory =, <, >, <=, >=, <> if (Z>= A ) and (Z<= Z ) then {hodnotou proměnné Z je velké písmeno anglické abecedy} while Z <> W do {dokud mají proměnné Z a W různou hodnotu} Pavel Töpfer, 2017 Programování 1-7 2
Standardní funkce var Z, Z1: char; B: byte; B := ord(z); Z := chr(b); vrací kód znaku Z v ASCII-tabulce (ordinální hodnotu) k zadanému ASCII-kódu vrací příslušný znak - funkce navzájem inverzní tedy chr(ord(z)) = Z - z hlediska syntaxe jazyka jde o přetypování - v kódu se nic neděje (znak je stejně reprezentován svým kódem) Použití: B:=ord(Z) ord( 0 ); cifra její hodnota Z:=chr(B+ord( 0 )); hodnota 0..9 cifra Z1 := UpCase(Z) malá písmena anglické abecedy změní na velká, ostatní znaky ponechá beze změny Použití: místo delšího if UpCase(Z) = A then if (Z= A ) or (Z= a ) then Pavel Töpfer, 2017 Programování 1-7 3
Příklad: vstup čísla po znacích - co přibližně dělá procedura read - algoritmus: Hornerovo schéma var Zn: char; {čtené znaky} Hodn: integer; {číselná hodnota} Hodn:=0; read(zn); while (Zn>= 0 ) and (Zn<= 9 ) do Hodn := Hodn*10 + ord(zn) ord( 0 ); read(zn) end; {výsledná hodnota je v proměnné Hodn} Pro jednoduchost předpokládáme korektní vstup, bez vedoucích mezer. Pavel Töpfer, 2017 Programování 1-7 4
Znakové řetězce - standardní typ string type JmenoTypu = string [N]; N celočíselná konstanta udávající maximální délku stringu N je nejvýše rovno 255 pokud N neuvedeme, implicitní hodnota je 255 Příklad: type JmenoMesice = string[8]; var Mesic: JmenoMesice; {proměnná pro řetězce max. 8 znaků} S: string; {proměnná pro řetězce max. 255 znaků} Reprezentace proměnné: - jednorozměrné pole znaků indexované od 1 do N - vlastní evidence aktuální délky uloženého řetězce (v bytu s indexem 0 pozor při manipulaci, formálně je typu char) Pavel Töpfer, 2017 Programování 1-7 5
Konstanty: duben řetězec délky 5 znaků? řetězec délky 1 znak (jako char) prázdný řetězec (žádný znak) Operace se stringy: - do proměnné lze dosazovat, např. Mesic := duben ; nastaví se tím aktuální délka (zde na 5) - jediný operátor + znamená zřetězení, např. po provedení S := 12. + Mesic; bude mít proměnná S hodnotu 12. duben a aktuální délku 9 - lze používat v procedurách read, write read(s); - načte tolik znaků, kolik je maximální délka S, nejvýše však do konce řádku na vstupu write(s); - vypíše tolik znaků, kolik je aktuální délka S Doporučení: Při čtení používat raději readln(s) přijdeme sice případně o znaky, které se nevešly do maximální délky S, zato při následujícím čtení budeme číst od začátku dalšího řádku. Jinak při čtení dalšího stringu ze vstupu načteme prázdný řetězec! Pavel Töpfer, 2017 Programování 1-7 6
Standardní procedury a funkce se znakovými řetězci Length(S) aktuální délka řetězce Concat(S1, S2,, Sn) spojení řetězců za sebe totéž se snáze zapíše operátorem + : S1 + S2 + + Sn Copy(S, Index, Pocet) vykopírování podřetězce dané délky počínaje od daného indexu Delete(S, Index, Pocet) v řetězci S zruší podřetězec dané délky počínaje od daného indexu Insert(Co, Kam, Index) do řetězce Kam vloží Co na pozici daného indexu Pos(Co, Kde) pozice prvního výskytu podřetězce Co v řetězci Kde (0 když tam není obsažen) Pavel Töpfer, 2017 Programování 1-7 7
Indexování: S[i] = i-tý znak řetězce S, je typu char S[2] := 5 ; for I:=1 to length(s) do if S[I] =? then S[I] :=! ; {v řetězci S nahradí všechny otazníky vykřičníkem} POZOR při indexování stringu změny neovlivňují aktuální délku: S:= ABC ; {aktuální délka S je 3} for I:= 1 to 10 do S[I]:= Z ; {do S se vloží 10 znaků, ale aktuální délka S zůstává nastavena na 3} write(s); {vypíše ZZZ } Uspořádání stringů - lexikografické, indukované uspořádáním na typu char 4 < Z < f < fa < fb < g < č < á - je možné používat relační operátory =, <, >, <=, >=, <> Pavel Töpfer, 2017 Programování 1-7 8
Příklad: načtení dlouhého čísla (kladné celé, max. 100 cifer) type Cislo = array [1..100] of byte; var A: Cislo; {A[1] cifra v řádu jednotek} PA: byte; {počet cifer} S: string[100]; I: integer; readln(s); PA := 0; for I:=length(S) downto 1 do inc(pa); A[PA] := ord(s[i])-ord( 0 ) end; Pavel Töpfer, 2017 Programování 1-7 9
Konverzní procedury Str(V, S) - konverze číselná hodnota V string S - V může být výraz typu integer nebo real - součástí V může být formátování V:n resp. V:n:m jako u write - volání Str se implicitně provádí v proceduře write (zápis čísla) Val(S, V, ErrCode) - konverze string S číselná hodnota V - V může být proměnná typu integer nebo real - ErrCode = 0 převod se povedl bez chyby - ErrCode > 0 pozice výskytu chyby (index v S) - volání Val se implicitně provádí v proceduře read (čtení čísla) Pavel Töpfer, 2017 Programování 1-7 10
Číselné soustavy - převod z dvojkové soustavy na číselnou hodnotu - algoritmus: Hornerovo schéma 110010 1.2 5 + 1.2 4 + 0.2 3 + 0.2 2 + 1.2 1 + 0.2 0 = = ((((1.2 + 1).2 + 0).2 + 0).2 + 1).2 + 0 = 50 - převod z šestnáctkové soustavy na číselnou hodnotu A1F A.16 2 + 1.16 1 + F.16 0 = = 10.16 2 + 1.16 1 + 15.16 0 = = (10.16 + 1).16 + 15 = 2591 Pavel Töpfer, 2017 Programování 1-7 11
program Bin_Dec; {převod čísla z dvojkové soustavy - Hornerovo schéma} var S: string[15]; {dvojkový zápis čísla} N: integer; {jeho hodnota} I: integer; read(s); N:=0; for I:= 1 to length(s) do N:=N * 2 + ord(s[i]) - ord('0'); writeln('hodnota: ', N) end. Pavel Töpfer, 2017 Programování 1-7 12
program Hex_Dec; {převod čísla z šestnáctkové soustavy - Hornerovo schéma} var S: string[15]; {šestnáctkový zápis čísla} N: integer; {jeho hodnota} I: integer; read(s); N:=0; for I:= 1 to length(s) do if (S[I] >= '0') and (S[I] <= '9') then N:=N * 16 + ord(s[i]) - ord('0') else N:=N * 16 + ord(s[i]) - ord('a') + 10; end; writeln('hodnota: ', N) end. Pavel Töpfer, 2017 Programování 1-7 13
110010 1.2 5 + 1.2 4 + 0.2 3 + 0.2 2 + 1.2 1 + 0.2 0 = = ((((1.2 + 1).2 + 0).2 + 0).2 + 1).2 + 0 = 50 - převod číselné hodnoty do dvojkové soustavy - algoritmus: Hornerovo schéma využité v opačném směru posloupnost zbytků při celočíselném dělení dvěma tvoří odzadu dvojkový zápis čísla připojování dvojkových cifer do stringu zleva 50 : 2 = 25, zb. 0 25 : 2 = 12, zb. 1 12 : 2 = 6, zb. 0 6 : 2 = 3, zb. 0 3 : 2 = 1, zb. 1 1 : 2 = 0, zb. 1 Pavel Töpfer, 2017 Programování 1-7 14
program Dec_Bin; {převod čísla do dvojkové soustavy - obrácené Hornerovo schéma} var S: string[15]; {dvojkový zápis čísla} N: integer; {jeho hodnota} read(n); S:=''; {prázdný řetězec} while N > 0 do if odd(n) then S:='1'+S else S:='0'+S; N:=N div 2 end; writeln('dvojkový zápis čísla: ', S) end. Pavel Töpfer, 2017 Programování 1-7 15
program Dec_Hex; {převod čísla do šestnáctkové soustavy - obrácené Hornerovo schéma} var S: string[15]; {šestnáctkový zápis čísla} N: integer; {jeho hodnota} Z: integer; read(n); S:=''; {prázdný řetězec} while N > 0 do Z:=N mod 16; if (Z <= 9) then S:= chr(z + ord('0')) + S else S:= chr(z 10 + ord('a')) + S; N:=N div 16; end; writeln('šestnáctkový zápis čísla: ', S) end. Pavel Töpfer, 2017 Programování 1-7 16
Rychlé umocňování aplikace dvojkové soustavy Úkol: spočítat hodnotu X N, kde - N je velké kladné celé číslo - X může být reálné číslo nebo třeba matice Řešení: - přímočaře v čase O(N): V:=1; for i:=1 to N do V:=V * X; - rychleji v čase O(log N): postupně počítáme hodnoty X, X 2, X 4, X 8, a vhodné z nich násobíme do výsledku V Pavel Töpfer, 2017 Programování 1-7 17
Které hodnoty X k jsou ty vhodné? Pozorování: X 25 = X 16. X 8. X 1, neboť 25 = 16 + 8 + 1 - to je jednoznačný rozklad čísla N na součet mocnin dvojky - jsou to ty mocniny dvojky, kde je jednička v binárním zápisu čísla N Postup je tedy podobný, jak převod čísla do dvojkové soustavy. V:=1; while N > 0 do if odd(n) then V:=V * X; X:=X * X; N:=N div 2 end; Časová složitost O(log N) počet opakování while-cyklu. Pavel Töpfer, 2017 Programování 1-7 18
Textové soubory - data uložena jako posloupnost ASCII-kódů jednotlivých znaků - lze číst a vytvářet v textovém editoru, čitelné pro člověka (narozdíl od binárních souborů budou později) - při čtení (zápisu) čísel se automaticky provádí konverze z (do) textové podoby do (z) vnitřního tvaru jako implicitní volání konverzních procedur Val a Str - soubor je vždy otevřen jen pro čtení nebo jen pro zápis - výhradně sekvenční přístup čte (zapisuje) se postupně od začátku - standardní vstup a výstup dat (z klávesnice, na obrazovku) jsou jen zvláštním případem textových souborů (tzv. pseudosoubory) 1. deklarace var T: text; 2. přiřazení assign(t, S); S je výraz typu string (často konstanta nebo proměnná), určuje fyzickou adresu souboru na disku např. assign(t, C:\Data\Vstupni1.txt ); Pavel Töpfer, 2017 Programování 1-7 19
3. otevření reset(t); - pro čtení soubor musí existovat! rewrite(t); - pro zápis vytváření nového append(t); - pro zápis připsání na konec existujícího souboru 4. operace vstupu a výstupu read(t, ); readln(t); write(t, ); writeln(t); write(t, A:n, R:n:m); - již známe pro standardní vstup a výstup, jen navíc jako první parametr uvést jméno souboru funkce typu boolean eof(t) konec souboru eoln(t) konec řádku seekeof(t) přeskočí případné bílé znaky a pak testuje konec souboru seekeoln(t) obdobně pro konec řádku 5. zavření close(t); Pavel Töpfer, 2017 Programování 1-7 20
Poznámky: - jeden soubor lze v programu otevřít postupně vícekrát (několikrát za sebou ho číst nebo třeba nejdříve ho vytvořit a pak po sobě číst) - pokud soubor existuje, provedením rewrite je nemilosrdně smazán (bez ověření dotazem) - při čtení čísel používat seekeof, seekeoln namísto běžných funkcí eof, eoln (pozor na případné bílé znaky za posledním číslem) - soubory zavírat (uvolnění systémových prostředků, jistota zápisu dat z vyrovnávací paměti na disk) - předdefinované proměnné input a output typu text spojené s klávesnicí a obrazovkou se automaticky doplňují do všech příkazů, v nichž není uvedeno jméno souboru - funkci eof lze použít i pro vstup dat z klávesnice (tzn. pro input, bez parametru), zadávání dat z klávesnice pak ale musí uživatel explicitně ukončit znakem EOF = #26 (pomocí Ctrl+Z) - pozor na čtení dat, když už eof(t)=true Pavel Töpfer, 2017 Programování 1-7 21
Chyby při I/O operacích = chyby při provádění operací se soubory, např. pokus o otevření neexistujícího souboru pro čtení nebo při pokusu o vstup čísla se ze souboru přečtou jiné znaky než číslice - reakce podle nastavení přepínače $I: {$I+} provádí se kontrola při výpočtu běhová chyba (standardní výchozí nastavení) {$I-} úspěšnost poslední I/O operace je programu pouze oznámena funkce IOResult typu integer: 0 = bez chyby nenulová hodnota = kód chyby Doporučení: - automatickou detekci I/O chyb vypínat jen pro mimořádné účely - při vypnuté kontrole {$I-} volat po každé I/O operaci IOResult (nastala-li chyba, všechny další I/O operace se ignorují až do zavolání funkce IOResult) Pavel Töpfer, 2017 Programování 1-7 22
Příklad využití {$I-} var Soubor: Text; Jmeno: string[50]; write( Zadej jmeno souboru: ); readln(jmeno); assign(soubor, Jmeno); {$I-} reset(soubor); {$I+} while IOResult <> 0 do writeln( Soubor, Jmeno, neexistuje! ); write( Zadej nove jmeno souboru: ); readln(jmeno); assign(soubor, Jmeno); {$I-} reset(soubor); {$I+} end; Pavel Töpfer, 2017 Programování 1-7 23