Implementarea produselor software necesită deseori, pentru a satisface
cerințele unui anumit set de date, structuri de date mai flexibile decât
înregistrările cu număr fix de componente. În astfel de situații este
convenabil să putem folosi înregistrări (articole) care să aibă o parte comună
și o parte a cărei structură să poată să fie diferită de la o înregistrare la
alta.
Să considerăm, de exemplu, că dorim să calculăm perimetrul unei figuri
geometrice care poate fi: triunghi, dreptunghi sau cerc. În toate cele trei
cazuri trebuie să reținem valoarea perimetrului dar, în plus, pentru păstrarea
lungimilor laturilor, respectiv a razei, sunt necesare trei câmpuri la
triunghi, două la dreptunghi și unul la cerc.
Un alt exemplu ar fi o listă de persoane care conține următoarele
informații despre fiecare persoană: numele, data nașterii,
starea civilă (necăsătorit, căsătorit, divorțat). În plus, pentru
persoanele căsătorite se mai înregistrează numele soțului/soției și numărul de
copii, iar pentru cele divorțate, data divorțului.
Articolele care permit mai multe variante de structuri de câmpuri se numesc
articole cu variante.
Pentru exemplele considerate anterior putem defini următoarele tipuri:
type
Fig = (Cerc, Triunghi, Dreptunghi);
Contur = record
Perimetru: real;
case Fel: Fig of
Triunghi: (Latura1, Latura2, Latura3: integer);
Cerc: (Raza: integer);
Dreptunghi: (Lungime, Latime: integer)
end; {Contur}
|
și respectiv:
const MaxPersoane = 50;
type
IndexPersoane = 1..MaxPersoane;
TipStareCivila = (Necasatorit, Casatorit, Divortat);
Data = record
Zi: 1..31;
Luna: 1..12;
An: 1900..3000;
end; {Data}
Persoana = record
Nume: string[20];
DataNasterii: Data;
Case StareCivila: TipStareCivila of
Necasatorit: ();
Casatorit: (NrCopii: integer; NumeSot: string[20]);
Divortat: (DataDivort: Data)
end; {Persoana}
ListaPersoane = array[IndexPersoane] of Persoana;
|
În legătură cu sintaxa înregistrărilor cu variante, există patru aspecte
importante care trebuie reținute:
-
Câmpul selector poate fi de orice tip ordinal; în mod frecvent (ca și în
exemplele anterioare) el va fi de tipul enumerare.
-
Sintaxa articolelor cu variante permite prezența unei singure clauze
case; pot exista însă clauze case imbricate (o clauză case în
cadrul altei clauze case), dar asemenea cazuri sunt rare.
-
Fiecare valoare a tipului selector trebuie sa apară ca și etichetă a
unei variante; daca varianta este vida (nu are nici un câmp) forma ei este:
constanta ( ).
-
Partea variantă trebuie sa fie întotdeauna ultima în structura unui
articol; nici o definiție de câmp nu mai poate să apară dupa ea. Un singur
cuvant cheie end marchează atât sfârșitul clauzei case cât și
a structurii record.
În ceea ce privește declararea unor variabile de tipul articol cu
variante, accesul la componente și operațiile permise, rămân valabile
toate aspectele studiate la tipul articol. Prin urmare, putem scrie
următoarele declarații:
pentru primul exemplu, și:
var Lista: ListaPersoane;
|
pentru cel de-al doilea exemplu.
După declararea unei variabile de tipul articol cu variante, câmpul
selector nu are asignată nici o valoare și este lipsită de sens referirea, în
această situație, la partea variantă. O soluție ar fi atribuirea, mai întâi, a
unei anumite valori câmpului selector și apoi referirea părții variante, ca în
secvențele următoare:
Figura.Fel := Cerc;
Figura.Raza := 4;
|
sau
Figura.Fel := Dreptunghi;
Figura.Lungime := 6;
Figura.Latime := 3;
|
Procedând astfel, ne vom referi doar la câmpuri care prezintă interes
pentru o anumită problemă. Selectarea operațiilor corespunzătoare unei anumite
variante se face, de obicei, în conjuncție cu instrucțiunea case.
Folosirea instrucțiunii case la prelucrarea articolelor cu variante
va fi exemplificată și în programele prezentate în secțiunea
exemple.
Trebuie reținut că o secvență de forma:
Figura.Fel := Cerc;
Figura.Lungime := 10;
|
... nu va fi semnalată ca eroare de compilare și programul va intra in
execuție. Prevenirea unor astfel de erori logice cade în responsabilitatea
programatorului.
-
Să se scrie un program care calculează perimetrul unei figuri
geometrice: triunghi, dreptunghi sau cerc, cunoscând dimensiunile laturilor,
respectiv raza.
Program PerimetruContur;
Type
Fig = (Cerc, Triunghi, Dreptunghi);
Contur = record
Perimetru: real;
Case Fel: Fig of
Triunghi: (Latura1, Latura2, Latura3: integer);
Cerc: (Raza: integer);
Dreptunghi: (Lungime, Latime: integer);
End; {Contur}
Var
Figura: Contur;
Raspuns: char;
function Converteste(c: char): fig;
begin {converteste}
case c of
'T', 't': Converteste := Triunghi;
'C', 'c': Converteste := Cerc;
'D', 'd': Converteste := Dreptunghi;
end; {case}
end; {Converteste}
begin {programul principal}
repeat
repeat
write('Introduceti tipul figurii (T/D/C): ');
readln(Raspuns);
until Raspuns in ['T', 't', 'D', 'd', 'C', 'c'];
Figura.Fel := Converteste(Raspuns);
with Figura do
case Fel of
Triunghi:
begin {triunghi}
write('Introduceti lungimile laturilor: ');
readln(Latura1, Latura2, Latura3);
perimetru := Latura1 + Latura2 + Latura3;
writeln('Perimetru= ',Perimetru:6:2);
end; {Triunghi}
Cerc:
begin {cerc}
write('Introduceti raza: ');
readln(Raza);
perimetru := 2 * pi * Raza;
writeln('Perimetru= ', Perimetru:6:2);
end; {Cerc}
Dreptunghi:
begin {Dreptunghi}
write('Introduceti lungimea: ');
readln(Lungime);
write('Introduceti latimea: ');
readln(Latime);
perimetru := 2 * (Lungime + Latime);
writeln('Perimetru= ', Perimetru:6:2);
end; {Dreptunghi}
end; {case}
write('Continuati? (N pentru terminare): ');
readln(Raspuns);
until (Raspuns = 'N') or (raspuns = 'n');
end.
|
Click aici pentru sursa completă
(ex01_1.pas)
-
Să se scrie un program care citește datele corespunzătoare unei liste de
persoane: nume, data nașterii, starea civila
(necăsătorit, căsătorit, divorțat), numele soțului și numărul de
copii pentru persoanele căsătorite și data divorțului pentru cele
divorțate. Programul va efectua următoarele prelucrări:
-
Ordonează lista în ordinea alfabetică a numelor;
-
afișează numele și numărul de copii ale persoanelor care au mai mult
de doi copii.
program StareCivila;
const MaxPersoane = 50;
type
IndexPersoane = 1..MaxPersoane;
TipStareCivila = (necasatorit, casatorit, divortat);
Data = record
zi: 1..31;
luna: 1..12;
an: 1900..3000;
end; {data}
Persoana = record
Nume: string[20];
DataNasterii: data;
case StareCivila: TipStareCivila of
necasatorit: ();
casatorit: (nrCopii: integer; numeSot: string[20]);
divortat: (DataDivort: data);
end; {persoana}
ListaPersoane = array[IndexPersoane] of Persoana;
var
Lista: ListaPersoane;
NrPersoane: IndexPersoane;
function Transforma(c: char): TipStareCivila;
{stabileste starea civila a unei persoane}
begin
case c of
'n', 'N': transforma := necasatorit;
'c', 'C': transforma := casatorit;
'd', 'D': transforma := divortat;
end; {case}
end; {Transforma}
procedure CitesteData(var d: data);
{citeste o data calendaristica exprimata in zi,luna,an}
begin
with d do
begin
write(' zi: ');
readln(zi);
write(' luna: ');
readln(luna);
write(' an: ');
readln(an)
end;{with}
end; {CitesteData}
procedure CitesteLista(var N: IndexPersoane; var L: ListaPersoane);
{citeste numarul de persoane din lista si informatiile asociate lor}
var
I: IndexPersoane;
Raspuns: char;
begin
repeat
write('Introduceti numarul de persoane (1-', MaxPersoane, '): ');
readln(N);
until (N >=1 ) and (N <= MaxPersoane);
writeln('Introduceti lista de persoane');
for I := 1 to N do
begin
writeln(' Persoana ', I:3);
with L[I] do
begin
write('Numele: ');
readln(Nume);
writeln('Data nasterii: ');
CitesteData(DataNasterii);
repeat
write('Starea civila (N/C/D): ');
readln(Raspuns);
until Raspuns in ['N', 'n', 'C', 'c', 'D', 'd'];
StareCivila := Transforma(Raspuns);
case StareCivila of
Casatorit:
begin
write('Numele sotului/sotiei: ');
readln(NumeSot);
write('Numar copii: ');
readln(NrCopii);
end; {Casatorit}
Divortat:
begin
writeln('Data divortului: ');
CitesteData(DataDivort)
end; {Divortat}
end;{case}
end;{with}
end;{for}
end; {CitesteLista}
procedure Interschimba(var P1, P2: Persoana);
{interschimba continutul a doua variabile de tipul Persoana}
var Auxiliar: Persoana;
begin {Interschimba}
Auxiliar := P1;
P1 := P2;
P2 := Auxiliar;
end;{interschimba}
Procedure Ordoneaza(N: IndexPersoane; var L: ListaPersoane);
{ordoneaza alfabetic lista de persoane}
var
I: IndexPersoane;
Ordonat: boolean;
begin {Ordoneaza}
repeat
Ordonat := true;
for I := 1 to N-1 do
if L[I].Nume > l[I+1].Nume then
begin
Interschimba(L[I], L[I+1]);
Ordonat := false;
end;
until Ordonat;
end; {Ordoneaza}
procedure Afiseaza(N: IndexPersoane; L: ListaPersoane);
{afiseaza numele si nr-ul de copii pt pers cu mai multi copii}
var I: IndexPersoane;
begin
for I := 1 to N do
if L[I].StareCivila = Casatorit then
if L[I].NrCopii > 2 then
writeln(L[I].Nume:20, L[I].NrCopii:3);
end; {afiseaza}
begin{progr principal}
CitesteLista(NrPersoane, Lista);
Ordoneaza(NrPersoane, Lista);
Afiseaza(NrPersoane, Lista);
end.
|
Click aici pentru sursa completă
(ex01_2.pas)
-
Să se realizeze programul Pascal care execută următoarele operații:
-
Citește de pe mediul de intrare numele unui utilizator, care poate fi
un student sau un cadru didactic. Dacă este student se va citi numărul
său matricol, iar dacă este cadru didactic se va citi gradul
universitar (asistent, lector, conferențiar, profesor). Pentru toți
utilizatorii se va citi timpul lucrat pe calculator (zile, ore,
minute și secunde);
-
Afișează un tabel de forma celui ilustrat mai jos:
Nr
|
Nume
|
Grad Universitar
|
Timp lucrat
|
1
|
Popescu Doru
|
profesor
|
13h22min34sec
|
2
|
Manea Dorin
|
asistent
|
16h20min02sec
|
3
|
Alexa Ion
|
student/0987
|
20h45min56sec
|
4
|
George Marius
|
student/7865
|
24h00min00sec
|
Timp total lucrat
|
03z02h18min32sec
|
Tabelul va fi ordonat astfel încât cadrele didactice să apară primele,
în ordinea gradelor (pentru grade identice în ordinea descrescătoare a
timpului lucrat), iar studenții în ordinea alfabetică (pentru nume identice,
în ordinea crescătoare a numărului matricol).
-
Să se scrie un program care înregistrează publicațiile: reviste și
carti, dintr-o bibliotecă. Pentru fiecare publicație se precizează titlul,
domeniul, prețul și dacă este sau nu împrumutată. În plus, pentru cărți se
mai precizează: autorul și numărul de pagini, iar pentru reviste anul și
luna apariției. Programul trebuie să permită realizarea următoarelor
operații:
-
Introducerea unei publicații în bibliotecă;
-
Afișarea publicațiilor aparținând unui anumit domeniu, precizând dacă
sunt sau nu împrumutate;
-
Afișarea datelor despre o publicație pentru care se precizează titlul;
-
Marcarea împrumutului unei carți;
-
Marcarea înapoierii unei carți;