4. Typ pole 4.1 Jednorozměrná pole Pole je homogenní datová struktura, skládající se ze složek stejného typu. Složky se vzájemně rozlišují pomocí indexu. Indexy složek pole jsou hodnoty určitého typu - typ indexu pole, stanoveného popisem pole. Typ složek pole je také stanoven popisem pole, typ není nijak omezen - může to být jednoduchý i strukturovaný typ.
4.1 Jednorozměrná pole Př.: - deklarace typu pole type var vektor=array[1..3] of real; u,v:vektor; veta=array[0..79]of char; buffer:veta; kod=array[char] of integer; iso:kod; Hodnoty proměnných typu pole se obvykle mění tak, že se přiřazují hodnoty jednotlivým složkám. Přiřazovacím příkazem je však možné definovat i celou hodnotu proměnné typu pole za podmínky, že pole jsou shodného (pojmenovaného) typu. Př.: var u,v : vektor; w : array[1..3] of real; u:=v ... u[1]:=v[1]; u[2]:=v[2]; u[3]:=v[3]; u:=w ... nelze, nejsou stejného typu
var a : array[1 .. 10] of integer; i : integer; begin Př.: Ukázka naplnění pole var a : array[1 .. 10] of integer; i : integer; begin for i:=1 to 10 do a[i]:=i; end.
var a : array[1 .. 100] of real; i,n : integer; f:text; begin Př.: Ukázka načtení pole v cyklu se známým počtem opakování var a : array[1 .. 100] of real; i,n : integer; f:text; begin assign(f,'data.txt'); reset(f); read(f,n); for i:=1 to n do read(f,a[i]); for i:=1 to n do begin write(a[i]:8:2); if i mod 5 = 0 then writeln; end; end.
assign(f,'data.txt'); reset(f); n:=0; read(f,x); Př.: Ukázka načtení pole v cyklu s neznámým počtem opakování - na vstupu jsou kladná čísla, za nimi záporné var a : array[1 .. 100] of real; xreal i,n : integer; f:text; begin assign(f,'data.txt'); reset(f); n:=0; read(f,x); while x>=0 do begin inc(n); a[n]:=x; end; for i:=1 to n do begin write(a[i]:8:2); if i mod 5 = 0 then writeln; end.
var a,b : array[1 .. 10] of real; i,n : integer; ss:real; begin ... Př.: Ukázka výpočtu skalárního součinu var a,b : array[1 .. 10] of real; i,n : integer; ss:real; begin ... ss:=0; for i:=1 to n do ss:=ss + a[i]*b[i]; end.
assign(f,'data.txt'); reset(f); read(f,n); for i:=n downto 0 do Př.: Ukázka výpočtu hodnoty zadaného polynomu v zadanem bodě (Hornerovo schema) var a : array[0 .. 30] of real; i,n : integer; x,hp:real; begin assign(f,'data.txt'); reset(f); read(f,n); for i:=n downto 0 do read(f,a[i]); read(f,x); hp:=a[n]; for i:=n-1 downto 0 do hp:=hp*x + a[i]; ... end.
Př.: Vstupní údaje tvoří posloupnost nenulových dvojic reálných čísel - souřadnic bodů v rovině. Posloupnost je ukončena dvojicí nul, která do ní již nepatří. Posloupnost obsahuje maximálně 1000 bodů. Vyjádřete algoritmus pro nalezení souřadnic všech bodů, které jsou nejblíže počátku. var i,n,imax:integer; xp,yp,v,min:real; x,y:array[1..1000] of real; begin n:=0; min:=1e300; read(xp,yp); while (xp <> 0) or (yp <> 0) do begin inc(n); v:=sqr(xp)+sqr(yp); if v < min then min:=v; x[n]:=xp;y[n]:=yp; end; for i:=1 to n do begin v:=sqr(x[i])+sqr(y[i]); if v = min then writeln(x[i]:8:2,y[i]:8:2) end.
Př.: Vstupní údaje tvoří posloupnost nenulových dvojic reálných čísel - souřadnic bodů v rovině. Posloupnost je ukončena dvojicí nul, která do ní již nepatří. Posloupnost obsahuje maximálně 1000 bodů. Vyjádřete algoritmus pro zjištění největší vzdálenosti mezi body. var i,j,n:integer; xp,yp,v,max:real; x,y:array[1..1000] of real; begin n:=0; max:=-1e300; read(xp,yp); while (xp <> 0) or (yp <> 0) do begin inc(n); x[n]:=xp;y[n]:=yp; end; for i:=1 to n-1 do for j:=i+1 to n do begin v:=sqr(x[i]-x[j])+sqr(y[i]-y[j]); if v > max then max:=v; writeln(sqrt(max):8:2); end.
program cetnost_znaku; var tab : array['a' .. 'z'] of integer; Př.: Program pro zjištění četnosti výskytu jednotlivých znaků textového vstupu. program cetnost_znaku; var tab : array['a' .. 'z'] of integer; zn : char; begin for zn := 'a' to 'z' do tab[zn] := 0; while not eof do begin read(zn); if (zn >= 'a') and(zn <= 'z') then tab[zn] := tab[zn] + 1; end; writeln(zn,' - ', tab[zn]:5); end.
4.2 Vícerozměrná pole Na typ pole nejsou žádné omezení, složky pole mohou být libovolného strokturovaného typu - i typu pole: type matice = array[1..10] of array[1..20] of real;... matice = array[1..10,1..20] of real; Struktura pole je definována rekurzivně - n-rozměrné pole je pole, jehož složky jsou n-1 rozměrná pole. Přístup k jednotlivým složkám: x[1][1][1] ... x[1,1,1] var mat:matice ... mat[i] je proměnná typu array[1..20] of real - i-tá složka proměnné mat - i-tý řádek matice
Př.: Vynulování matice - průchodem přes všechny prvky var mat : matice; ... for i:=1 to 10 do for j:=1 to 20 do mat[i,j]:=0; {200x} - kopírováním celého vektoru for i:=1 to 20 do mat[1,i]:=0; {20x} for i:=2 to 10 do mat[i]:=mat[1]; {9x}
Př.: Výměna dvou řádků matice - průchodem přes všechny prvky var mat : array[1..10,1..20] of real; pom : real; for j:=1 to 20 do begin pom:=a[k,j]; a[k,j]:=a[l,j]; a[l,j]:=pom; {60x} end; - kopírováním celého vektoru type radek=array[1..20] of real; matice=array[1..10] of radek mat : matice; pom : radek; ... pom:=mat[k]; mat[k]:=mat[l]; mat[l]:=pom; {3x} Proměnné pom a mat[i] musí být stejného (pojmenovaného) typu - radek, nestačí pouze stejný rozměr.
program nasobeni_matic; var a,b,c : array[1..10,1..10] of real; i,j,k,n : integer; s : real; begin read(n); for i := 1 to n do for j := 1 to n do read(a[i,j]); read(b[i,j]); for j := 1 to n do begin s := 0; for k := 1 to n do s := s + a[i,k] * b[k,j]; c[i,j] := s; end; for i := 1 to n do begin {tisk dvou matic vedle sebe} for j := 1 to n do write(a[i,j]); write(' '); for j := 1 to n do write(b[i,j]); writeln; for i := 1 to n do begin {tisk matice} end.
Př.: V zadané obdélníkové matici najděte všechny řádky, které tvoří navzájem kolmé vektory. program kolme_radky_matice; var a : array[1..10,1..10] of real; i,j,k,m,n : integer; s : real; begin read(m,n); for i := 1 to m do for j := 1 to n do read(a[i,j]); for i := 1 to m-1 do for j := i+1 to m do begin s := 0; for k := 1 to n do s := s + a[i,k] * a[j,k]; if s=0 then writeln('Radky ',i,' a ',j,' jsou kolme'); end; end.
Př.: V zadané obdélníkové matici najděte sloupec s největším součtem. program max_soucet_slouce; var a : array[1..10,1..10] of real; i,j,m,n,jmax : integer; s,max : real; begin read(m,n); for i := 1 to m do for j := 1 to n do read(a[i,j]); max:=-1e30; for j := 1 to n do begin s:=0; s:=s + a[i,j]; if s > max then begin max:=s; jmax:=j; end; writeln('Nejvetsi soucet ',s:8:2,' je ve sloupci ',jmax); end.
4.3 Řetězce V pascalu je definován typ packed array of char - kompresované pole znaků, který neni v TP implementován. Obyčejné pole znaků je pro ukládání řetězců nepraktické. V TP je definován speciální typ řetězec - string. Hodnota proměnné typu string je posloupnost znaků s atributem aktuální délky řetězce (momentální délka řetězce během vykonávání programu) a s atributem konstantní délky řetězce v rozsahu 0..255. Př.: type string8=string[8]; var s1,s2 : string8; s : string;
4.3 Řetězce I- tý znak řetězce je zpřístupněn pomocí indexu . Zápis s[i] znamená hodnotu typu char. Proměnná i může nabývat hodnot z intervalu od 0 po velikost atributu konstantní délky. Řetězec délky n je tedy definován jako pole znaků o n+1 prvcích. První znak řetězce s[0] je znak, jehož ordinální číslo (ASCII kod) představuje skutečnou délku řetězce - atribut aktuální délky. Pro zjištění aktuální délky řetězce slouží funkce length(s), která je ekvivalentní výrazu ord(s[0]). Znaky za dynamickou délkou jsou náhodné. Je možno k nim přistupovat pomocí indexu - kompilátor nekontroluje překročení indexu přes aktuální délku.
Operace s řetězci: - operace zřetězení dvou řetězců : var s1, s2: string; ... s1 + s2 - Výsledek je řetězec délky, která je součtem délek s1 a s2; je-li součet délek větší než atribut konstantní délky proměnné, do níž se má uložit, je přebytečná část stracena. - relační operace: =,<>,<,>,>=,<= - porovnávají řetězce znak po znaku podle jejich ordinálních čísel. U nestejně dlouhých řetězců se považuje každý znak, který nemá partnera za větší: ‘xxa’>‘xx’. Konstanty typu řetězec se zapisují v jednoduchých uvozovkách 'abc', prázdný řetězec ''.
Podprogramy pro práci s řetězci Procedury: delete, insert, str, val. Funkce: concat, copy, length, pos. Delete - vypuštění podřetězce z řetězce: procedure delete(var s:string; index,count:integer); - z řetězce s vypustí od pozice index počet znaků daný count. s:='123456789'; delete(s,3,4); {... s='12789'} Insert - vložení podřetězce do řetězce procedure insert(source:string; var s:string; index:integer); - do řetězce s vloží od pozice index řetězec source. s:='12789'; insert('3456',s,3); {... s='123456789'}
Podprogramy pro práci s řetězci Str - převádí numerickou hodnotu (reálnou nebo celočíselnou) na výraz typu string, formát výsledku je stejný jako u write procedure str(x[:i[:j]]; var s:string); str(1.2345:8:3,s) ... s='~~~1.235' Val - převádí řetězec na číslo (reálné nebo celé) procedure val(s:string; var v:; var code:integer); s musí obsahovat syntakticky správný zápis čísla typu real nebo integer; dojde-li při převodu k chybě, vrací proměnná code pozici nesprávného znaku v řetězci. Před číslem nesmí být mezery. Proměnná v musí být odpovídajícího typu. val('1.23',r,c); val'123',i,c);
Podprogramy pro práci s řetězci Concat - spojení více řetězců do jednoho function concat(s1[,s2,...,sn]:string):string; s:=concat('123','456','789'); ... s='123456789' Copy - výběr podřetězce z řetězce function copy(s:string;index,count:integer):string; funkce vrací podřetězec z řetězce s od pozice index délky count s:='123456'; s:=copy(s,3,2); {... s='34'}
Podprogramy pro práci s řetězci length - délka řetězce function length(s:string):integer; pos - prohledá řetězec na výskyt podřetězce function pos(substr,s:string):integer; Vyhledá první pozici výskytu podřetězce v řetězci, není-li nalezen, vrací nulu.
Podprogramy pro práci s řetězci Př.: Nahrazení mezer před číslem nulami s:='~~~1.234'; while pos('~',s)>0 do s[pos('~',s)]:=0; {... s='0001.234'} Př.: Odstranění mezer z řetězce s:='~~~1.234~'; while pos('~',s)>0 do delete(s,pos('~',s),1); {... s='1.234'} var s1,s2:string; i:integer; s1:='~~~1.234~'; s2:=''; for i:=1 to length(s1) do if s1[i] <> '~' then s2:=s2+s1[i];
Př.: Převrácení řetězce var s1,s2 : string; i,n : integer; begin readln(s1); n := length(s1); for i := 1 to n do s2[i] := s1[n-i+1]; s2[0]:=chr(n); writeln(s2); end. var s1,s2 : string; i,n : integer; begin readln(s1); n := length(s1); s2:=''; for i := 1 to n do s2 := s2 + s1[n-i+1]; writeln(s2); end.
5. Deklarace typů, výčtový typ, typ interval Datový typ představuje atribut datového objektu, specifikujícímnožinu přípustných hodnot a množinu přípustných operací. Existuje sedum tříd typů: - výčtový - interval - množina - pole - záznam - soubor - ukazatel Každá třída má zavedenu konstrukci, pomocí níž se definují konkrétní typy této třídy Př.: array[boolean] of integer.
Deklarace typů, výčtový typ, typ interval Popis typu se může vyskytovat jako označení typu v deklaraci proměnné (tzv. nepojmenované typy) nebo se typ definuje společně s jeho jménem - identifikátorem typu. (pojmenované typy). Pojmenované typy se zavádějí v úseku deklarace typů. Př.: type index=1..50; vektor=array[index] of integer; znaky=set of char; vekt=array[index] of integer; Deklarace se skládá z identifikátoru typu a popisu typu. Pro typovou kontrolu je důležité, že každým výskytem popisu typu se definuje nový typ různý od všech ostatních ... vekt<>vektor. var x:array[index] of integer; ... proměnná x nepojmenovaného typu, který je různý od vekt a vektor.
Výčtový typ Tento typ se používá v případě potřeby vyjádřit malý počet hodnot. Jeho použití zvyšuje čitelnost a srozumitelnost programu. Symbolické hodnoty můžeme kódovat pomocí přirozených čísel 0,1,2, ... nebo využitím výčtového typu. Př.: type stav = (svobodny,zenaty,rozvedeny,vdovec); den = (pondeli,utery, ... ,nedele); Výčtový typ je ordinální typ a jsou pro něj definovány relační operace a standardní funkce ord, succ, pred. Uspořádání hodnot výčtového typu je dáno poředím identifikátorů v definičním seznamu. První položka má nejmenší hodnotu, její ordinální číslo je 0. ord(pondeli)=0, ord(utery)=1, utery<streda, succ(utery)=streda.
Výčtový typ Pro výčtový typ nejsou definovány žádné další operace. Chceme-li provést výpis hodnot výčtového typu: var s:den; ... case s of pondeli : writeln('pondeli'); utery : writeln('utery'); end;
Typ interval Specifikuje neprázdnou souvislou podmnožinu hodnot nějakého ordinálního typu. Interval je určen dolní a horní mezí , které jsou tvořeny konstantami daného typu: type tden = (pondeli,utery,....nedele); tcislice = '0' .. '9'; tpracden = pondeli .. patek; tkladna_cisla = 1 .. maxint; tzaporna_cisla = -maxint .. -1;
Typ interval Deklaraci proměnné typu interval provedeme pomocí pojmenovaného typu nebo přímo: var pocet : 1 .. 100; pracden : pondeli .. patek; Stanovením intervalu jako typu proměnné se omezuje množina přípustných hodnot proměné. Kontrola přípustnosti se provádí obvykle až v době výpočtu.