Compatibilitatea enunturilor de atribuire

Desi, la prima vedere enunturile de atribuire:

"variabila" := "expresie"

nu par a ridica nici o problema, va asiguram ca lucrurile nu stau chiar atāt de simplu, pe cāt s-ar parea.

Compilatorul (Borland) PASCAL este foarte fericit cānd atribuim expresii īntregi variabilelor īntregi, expresii booleene variabilelor booleene si tot asa pentru fiecare tip studiat.

Dar nu īntotdeauna lucrurile stau asa. In comentariul nostru privind compatibilitatea enunturilor de atribuire vom considera, pentru īnceput, atribuirile de tip mixt (hibrid).

Tipuri mixte

Consideram urmatoarea secventa (Borland) PASCAL:

...
VAR
...a:real;
...j:integer;
BEGIN
...a:=7;
...j:=3.8;
...

Dupa cum observati, am atribuit un īntreg (7) unei variabile de tip real (a) si un numar real (3.8) unei variabile de tip īntreg (j). Ne īntrebam daca cele doua enunturi de atribuire sunt valide ? Pentru primul enunt se impune convertirea 7.0, lucru care de altfel se si īntīmpla, automat. Similar, fie 3 sau 4 care poate fi atribuit īn mod rezonabil, variabilei j. In acest caz, trebuie specificata, īn mod explicit o functie de transfer. Programatorul care concepe acest program trebuie sa prevada una din urmatoarele expresii.

j:= trunc(3.8); j:= round(3.8);

Remarca.

Evident, exemplul este stupid. Daca doriti, neaparat ca j sa aiba valoarea 3 , puteti scrie simplu j:=3;.

Fundamentarea matematica privind atribuirea de catre compilatorul (Borland) PASCAL a valorilor reale, variabilelor de tip īntreg, este ilustrata īn diagrama urmatoare.

Punctele de corespondenta reali-īntregi

Axa reala este figurata ca fiind continua: spatiile micute dintre numerele reale adiacente sunt figurate mai putin corect - ele sunt prea mici pentru a putea fi observate.

Pe axa īntregilor, fiecare punct este un īntreg. Pentru fiecare punct situat pe axa īntregilor exista un punct pe axa reala ce corespunde unui numar real care se īntīmpla sa nu aiba parte fractionara. Asadar, nu mai exisa nici un dubiu privind modul prin care un īntreg este convertit la un numar real. Dar atentie, reciproca nu este adevarata! Foarte multe puncte de pe axa reala nu au un punct corespunzator pe axa īntregilor.

In concluzie, cānd scriem programul (Borland) PASCAL trebuie sa convertim valorile reale la īntregi printr-o alegere explicita fie a lui round sau trunc.


Alta metoda de a schimba tipurile de date este cea a utilizarii masivelor.

In programul schimb, variabila tabel a fost declarata ca fiind de tipul ARRAY ['A'..'Z'] of char.

S-a īntāmplat ca acest masiv sa aiba index-urile si componentele, ambele de acelasi tip - char. Dar, de foarte multe ori dorim sa folosim index-uri de un tip si componente de alt tip, lucru perfect posibil īn (Borland) PASCAL.

De exemplu, ord si chr sunt functii inverse; chr (ord(c))=c. Dar aceasta relatie nu poate fi retinuta pentru elemente de tip enumerare.

TYPE
...zi = (luni, marti, miercuri, joi, vineri);

In acest caz, putem merge de la element la īntreg. De exemplu, ord(miercuri)=2.

Remarca.

PASCAL-ul standard, spre deosebire de (Borland) PASCAL, nu are o functie de transfer, pentru a transforma 2 , de exemplu, īn miercuri.

Sa presupunem, ca definim:

VAR
...v : ARRAY [0..4] of zi;

Vom initializa de asemenea, componentele lui v cu valorile corespunzatoare lui zi. Dupa aceea , daca n este un īntreg cu valori de la 0 la 4 īl putem folosi pentru indexarea masivului v īn scopul obtinerii celui de-al n-lea element apelat (ca si o functie de transfer).

Programul urmator ilustreza aceasta tehnica, rugāndu-va sa completati spatiile libere, marcate cu "?" si apoi sa introduceti si sa executati programul. Bafta!

PROGRAM transfer;
{Converteste intregii cititi īn input in elementele unui tip enumerare}
TYPE
...zi=(luni, marti, miercuri, joi, vineri);
VAR
...v:ARRAY [0..4] of zi;
...raspuns:integer;
BEGIN
{initializare componente v}
...v[0]:=luni;
...v[1]:=marti;
...v[2]:=miercuri;
...v[3]:=joi;
...v[4]:=vineri;
...writeln(' MENU ');
...writeln(' 0 luni ');
...writeln(' 1 marti ');
...writeln(' 2 miercuri ');
...writeln(' 3 joi ');
...writeln(' 4 vineri ');
...writeln(' Introduceti un īntreg de la 0 la 4');
...readln(raspuns);
...if NOT (raspuns in [0..4]) THEN writeln ('eroare') else
...if v[raspuns] = luni THEN writeln('...?...') else
...if v[raspuns] = marti THEN writeln('...?...') else
...if v[raspuns] = miercuri THEN writeln('...?...') else
...if v[raspuns] = joi THEN writeln('...?...')
...if v[raspuns] = vineri THEN writeln('Felicitari!')
END {transfer}.

Remarca.

Utilizarea masivelor permite programatorului sa realizeze orice functie de transfer care lipseste PASCAL-ului.

Revenind la datele de tip subdomeniu. Faptul ca atāt variabila cāt si expresia implicata īntr-un enunt de atribuire ("variabila":="expresie") sunt de acelasi tip, nu garanteaza compatibilitatea atribuirii.

Consideram urmatoarele declaratii:

Exemplu:
TYPE
...a=0..40;
...b=30..60;
...c=100..500;
Var
...d:a;
...e:b;
...f:c;

Ne punem urmatoarea īntrebare: ce fel de atribuiri putem realiza cu variabilele d, e, f, toate fiind de tipul integer? Atribuirea f:=400 este categoric valida (400 se afla īn subdomeniul 100..500). Dar f:=600 nu este un enunt valid īntrucāt limita superioara a lui c este 500. Ce se īntāmpla daca f:=e ? Si acest enunt este invalid (domeniul asociat lui e (30..60) nu se suprapune peste domeniul lui f). Ce se īntāmpla daca e:=d? Raspunsul depinde de valoarea curenta a lui d (valorile cuprinse īntre 30..40 sunt singurele care fac parte din domeniul care se suprapune peste cel al lui e).