6. Typ záznam Strukturovaný datový typ - znamená spojení několika elementů stejného nebo různých typů do jedné proměnné. Např. pole je strukturovaný datový typ, kde jednotlivé položky jsou stejného typu (homogenní datová struktura). Záznam - je nehomogenní datová struktura, skládající se z pojmenovaných složek různého typu. Složky nazýváme položkami záznamu. Jména a typy položek záznamu se specifikují popisem typu záznam tvaru: record seznam položek end;
Type complex = record re,im : real end; datum = record den : 1..31; mesic : 1..12; rok : 1900..2000 end; pracovnik = record jmeno : string[8]; primeni : string[15]; narozen : datum; pohlavi : (muz,zena); stav : (svobodny, zenaty, rozvedeny, vdovec)
Přístup k jednotlivým položkám proměnných typu záznam se provádí pomocí selektoru záznamu tvaru: proměnná typu zaznam. identifikátor položky. var x,y : complex; dnes : datum; zamestnanec : pracovnik; kartoteka : array [1..1000] of pracovnik; x.re, x.im ... proměnné typu real, dnes.mesic ... typu 1..12, zamestnanec.jmeno[1] ... typu char, kartoteka[1].stav ... výčtového typu.
Hodnota proměnné typu záznam může být přiřazena jediným přiřazovacím příkazem jiné proměnné téhož typu: zamestnanec :=kartoteka[7] Proměnnou typu záznam je možno číst nebo zapisovat pouze u typových souborů. Čtení a zápis u textových souborů je třeba provádět po jednotlivých položkách.
Příkaz with Pokud na malém úseku programu použijeme několikrát některou položku záznamu nebo několik položek téže proměnné typu záznam, můžeme zápis zkrátit pomocí příkazu with: with dnes do begin den:=10; mesic:=3; rok := 1990 end; Přístup k proměnné typu záznam se v příkazu with provede pouze jednou, což vede také ke zrychlení programu, zvláště v případě, že záznam je položkou pole: with kartoteka[i] do begin write(jmeno,primeni); with narozen do begin write(den, mesic,rok);
Dvojitý příkaz with je možno zjednodušit: with z1 do with z2 do ... with z1,z2 do Uvnitř tohoto příkazu lze zkráceně označovat jednak položky záznamu z2, jednak ty položky záznamu z1, jejichž identifikátory se nezhodují s žádným identifikátorem položky záznamu z2 ( zastínění nelokálního významu).
Př.1.: Načtení a uložení záznamů do souboru. program zaznamy1(input,seznam); type datum = record den : 1..31; mesic : 1..12; rok : 1900 .. 2100; end; zaznam = record primeni : string[15]; jmeno : string[8]; datnar : datum var osoba : zaznam; soubor : file of zaznam; i : integer;
begin assign(soubor,'sezn.vst'); rewrite(soubor); writeln('program pro zadani seznamu osob'); write('primeni : '); while not eof do begin read(osoba.primeni); readln; write('jmeno : '); read(osoba.jmeno); writeln('datum narozeni'); write('den : '); readln(osoba.datnar.den); write('mesic : '); readln(osoba.datnar.mesic); write('rok : '); readln(osoba.datnar.rok); write(soubor,osoba); end; close(soubor); end.
Př.2.: Přečtení záznamů, setřídění a tisk. program zaznamy2(output,seznam); type datum = record den : 1..31; mesic : 1..12; rok : 1900 .. 2100; end; zaznam = record primeni : string[15]; jmeno : string[8]; datnar : datum var osoba : zaznam; soubor : file of zaznam; i,j,k : integer; poleosob : array[1..1000] of zaznam; pomosoba : zaznam;
begin assign(soubor,'sezn.vst'); reset(soubor); k := 0; writeln('program pro tisk setrideneho seznamu osob'); while not eof(soubor) do begin k := k + 1; read(soubor,poleosob[k]); end; for i := 1 to k-1 do for j := i + 1 to k do if (poleosob[j].primeni>poleosob[i].primeni) or ((poleosob[j].primeni=poleosob[i].primeni)and (poleosob[j].jmeno>poleosob[i].jmeno)) then pomosoba := poleosob[j]; poleosob[j] := poleosob[i]; poleosob[i] := pomosoba; writeln('primeni jmeno datum narozeni'); writeln('*************************************'); for i := i to k do with poleosob[i],datnar do begin write(primeni,' ':16-length(primeni)); write(jmeno,' ':9-length(jmeno)); writeln(den:2,'.',mesic:2,'.',rok:4); end.
Variantní záznamy Při návrhu datových struktur je někdy užitečné a přirozené považovat několik typů za různé varianty téhož typu, který je jejich sjednocením. Příklad takovéto struktury: type tmiry=(prsa,pas,boky); osoba=record primeni : string[20]; jmeno : string[10]; narozeni : datum; pohlavi : (muz,zena); stav : (svob,zenat, rozv, vdov); hmotnost : real; vous : boolean; miry : array[tmiry] of integer; end;
Předpokládejme, že nás nezajímají míry mužů ani hmotnost a výskyt vousu u žen. V případě pohlaví muž nás tedy zajímá váha a vous a v případě ženy míry. Typ osoba bude sjednocením dvou typů - variant: 1) prijmeni, jmeno, narozeni, stav, pohlavi, vaha, vous 2) -“ - , miry Typ specifikující několik variant záznamu se nazývá variantní záznam a má syntaxi: type typpohl = (muz,zena); tmiry = (prsa,pas,boky); osoba = record primeni : string[20]; jmeno : string[10]; narozeni : datum; stav : (svob,zenat, rozv, vdov); case pohlavi : typpohl of muz : (hmotnost:real; vous : boolean); zena : (miry : array[tmiry] of integer); end;
Pevná část specifikuje položky, které se vyskytují ve všech variantách Pevná část specifikuje položky, které se vyskytují ve všech variantách. Tato část může chybět. Za pevnou částí následuje rozlišovací položka, která je rozlišovacího tyu. Rozlišovací typ variantní části může být pouze ordinální typ a musí být označen identifikátorem typu. Za specifikací rozlišovací položky je uveden seznam, jímž se specifikují jednotlivé varianty této části záznamu. Specifikace každé varianty je uzavřena v závorkách. Příklad dvou hodnot různých variant: primeni jmeno narozeni stav pohlavi vaha vous Novak Jan 10.2.1960 svob muz 76 false primeni jmeno narozeni stav pohlavi miry Krausova Dana 11.4.1952 rozv zena 88 65 92
Př.: Zpracování kartotéky - nejtěžší muž a nejštíhlejší žena const maxpoc = 1000; var kart : array[1..maxpoc]of osoba; skutpoc, im,iz,i : 0..maxpoc; hm : real; pz : integer; begin ... hm := 0; pz := 1000; for i := 1 to skutpoc do begin with kart[i] do case pohlavi of muz : if hmotnost > hm then begin hm := hmotnost; im := i end; zena : if miry[pas] < pz then begin pz := miry[pas]; iz := i end.
Ja ko rozlišovací typ variantní části záznamu se používají nejčastěji výčtové typy, typ boolean, příp. interval. Norma pascalu požaduje pro každou hodnotu rozlišovací položky variantu záznamu - typy integer a char se nepoužívají pro rozlišení. V TP je použití těchto typů povoleno. Přiřadíme-li proměnné typu variantní záznam hodnotu odpovídající nějaké variantě, pak je chybou použití položky jiné varianty, ale překladač tyto chybu neindikuje: var zamestnanec:osoba; je-li hodnota proměnné zamestnanec.pohlavi = zena pak hodnota proměnné zamestnanec.hmotnost je náhodná
Variantní část záznamu může být specifikována také bez rozlišovací položky pouze určením rozlišovacího typu v případě, že variantu lze zjistit z kontextu: type druh_znaku = (pismeno, ostatni); velikost_pisma = (male, velke); ... znak = record zn : char; case druh_znaku of pismeno : (velikost : velikost_pisma); ostatni : (ridici_znak : boolean); end; Obrazec = record X, Y : Real; case Druh : (Obdelnik, Uhelnik, Kruh) of Obdelnik : (Sirka, Vyska : Real); Uhelnik : (N : Byte; RU : Real); Kruh : (RK : Real);