Jump to content

[PASCAL] Lectia 4 - Vectori (tablouri, matrici)


Leventhe
 Share

Recommended Posts

Vectori (tablouri, matrici)

 

Probabil ca acum, dupa ce ati parcurs primele 3 tutoriale de Pascal de pe aici, stiti sa faceti suma a doua numere, citite de la tastatura. Probabil ca vi se pare chiar usor. Sa zicem ca vreau sa-mi si afisati cele doua numere dupa ce-ati afisat suma. Nimic iesit din comun.

 

Ce-ati zice daca v-as cere un program care sa faca suma a trei numere ? E posibil sa nu va deranjeze prea tare ... nu e mare lucru sa adaugi o variabila, sa-i citesti valoarea de la tastatura si sa o aduni la suma. Chiar si afisarea celor trei numere nu ar trebui sa dea batai de cap nimanui.

 

Ce-ati zice daca v-as cere un program care face suma a 1000 de numere, afisand apoi fiecare numar introdus de la tastatura ?

 

E clar, e momentul pentru un alt tip de date, unul structurat, capabil sa tina in memorie siruri de date. Primul tip de date structurat care l-am prezentat in Tipuri de date in Pascal este tipul tablou. Pentru acest tip de date se folosesc mai multe sinonime, cum ar fi vector, matrice sau englezismul array. Toate se refera la acelasi lucru. Sa incepem cu inceputul.

 

Vectori unidimensionali

 

Ca sa putem folosi acest nou tip de date, trebuie sa-l declaram. Modalitatea de declarare a unui vector unidimensional cu capacitatea de 1000 de numere intregi (pe 2 bytes, in acest caz) este urmatoarea:

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

sir : array [1 .. 1000] of Integer;

 

So, punem cuvantul cheie "array", punem indexul de inceput al sirului (poate fi si -17 ), punem ".." pentru a specifica faptul ca e vorba de un interval, punem indexul de sfarsit (1000 in exemplul de mai sus), adaugam cuvantul cheie "of" (asa-i romanul, plin de ofuri ), specificam tipul datelor care vor face parte din vector ... si nimic mai mai mult.

 

Exemple

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

var test: array [65 .. 122] of char;

test2: array ['H' .. 'a'] of boolean;

 

Nu va speriati, si varianta in care am pus litere pe post de indecsi e functionala. Rar folosita, dar posibila. Deci ... un vector de caractere (cu indecsi intre 65 si 122 ... si un vector de valori logice, intre 'H' si 'a' ... adica un vector cu 25 de pozitii).

 

Cum se spune, nimic mai simplu. Avem variabila sir care are 1000 de pozitii si imi permite sa salvez cate un numar pe fiecare dintre aceste pozitii. Singura (posibila) problema este faptul ca nu putem salva decat numere intregi in acest sir. Elementele unui vector trebuie sa aiba acelasi tip.

 

Nu se pot defini vectori ale caror elemente sa fie fisiere.

 

Modalitatea de accesare a unei anumite pozitii din sir se face scriind numele sirului (sir in cazul acesta) si, intre paranteze drepte, [ si ], indicele (pozitia) din sir care o dorim.

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

sir[17] := 2342;

 

In acest fel, fiecare pozitie a vectorului poate fi privita ca o variabila de sine statatoare, scrisa putin mai ciudat.

 

Atentie: Nu confundati pozitia unui element din vector cu valoarea lui.

Daca am valorile urmatoare in vector (in ordine): 159, 65, 78, 23, 72, 34 ... atunci elementul de pe pozitia 3 are valoarea 78. Atentie maxima, am vazut multe aiureli cauzate de confuzii de acest gen.

 

Alta problema destul de comuna este incercarea de a folosi vectori care ocupa mai mult decat capacitatea de memorie alocata de catre Pascal. Aceste incercari vor determina compilatorul de Borland Pascal 7.0 sa genereze o eroare de compilare cu mesajul "Structure too large".

 

Compilatorul de Borland Pascal 7.0 ofera un spatiu de memorie de maxim 64KB per fisier al programului (momentan, un singur fisier). Exista alte compilatoare care ofera mult mai mult si care, evident, nu dau asemenea erori.

 

Stiind ca un element al unui vector este apelat folosind indexul lui, devine deja clar ca putem folosi bucle pentru lucrul cu vectori.

 

Hai sa vedem cum citim 1000 de numere, folosind vectori si o bucla For (daca nu mai stiti ce e o bucla For, Instructiuni repetitive va mananca ).

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var sir : array [1 .. 1000] of Integer;

i, n: Integer;

begin

Write('Dati numarul de valori care doriti sa le introduceti: ');

ReadLn(n);

 

For i := 1 To n Do {citim toate elementele de la tastatura ...}

begin

Write('Dati elementul ', i : 4, ' : ');

ReadLn(sir); {... si le salvam in vector}

end;

ClrScr;

 

For i := 1 To n Do {afisam elementele citite de la tastatura}

Write(sir:8);

ReadLn;

end.

 

Pentru amuzament, hai sa dam valorile elementelor din vector in felul urmator: pe o pozitie sa fie valoarea 1, pe urmatoarea sa fie valoarea 0, pe urmatoarea pozitie iar 1, and so on.

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var sir : array [1 .. 1000] of Integer;

i, n: Integer;

begin

Write('Dati numarul de valori care doriti sa le introduceti: ');

ReadLn(n);

 

For i := 1 to n Do {aici se pune 1, 0, 1, 0, 1 ...}

sir := i mod 2; {simplu, nu ?}

 

For i := 1 To n Do {afisam elementele}

Write(sir:8);

ReadLn;

end.

 

Cam asta ar fi ce este de explicat la vectorii unidimensionali, acum puneti-va centura de siguranta pentru ...

 

Vectori multidimensionali

 

Care-i problema cu vectorii astia ? De ce nu pot fi toti la fel ? De ce ne trebuie vectori unidimensionali, si bidimensionali, si tridimensionali, si dimensionali intr-o dimensiune pe care nu o pot vizualiza ... ?

 

Raspunsul e simplu: nu stiu

 

Vectorii unidimensionali, intr-un mod cat se poate de evident, aveau o singura dimensiune, lungime, care era definita de numarul de elemente din ei. Hai sa ne imaginam vectorul unidimensional ca pe o linie din foaia de matematica: un sir de casute, nu ? Fiecare casuta accepta o cifra (sau, daca scrii ca mine, trei ), deci fiecare element e de acelasi tip.

 

Totusi, foaia de matematica are doua dimensiuni, lungime si latime. E un tabel. Cum definesti un vector unidimensional in asa fel incat sa-l poti folosi ca pe un tabel ? Nu o faci. Folosesti un vector bidimensional, care este chiar un tabel, nu ?

 

P.S. ca informatie relativ utila, vectorii unidimensionali pot fi folositi ca vectori multidimensionali. Memoria video este vazuta, practic, ca un vector unidimensional, dar noi o vedem bidimensional. Asta va spune ceva ?

 

Hai sa vedem cum definim un vector bidimensional, fiindca sunt sigur ca nici nu va trece prin cap

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

tabel = array [1.. 10, 1 .. 20] of integer;

 

Asemanator cu vectorii unidimensionali, nu ? Primul set (1 .. 10) determina numarul de linii, iar al doilea numarul de (20 de) coloane.

 

Accesul la elementul de pe o anumita pozitie necesita acum doi indecsi, ceea ce e normal:

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

tabel[2, 5] := 124;

 

Codul acesta poate fi citit in felul urmator: elementul de pe linia 2, coloana 5 din matricea denumita "tabel" va lua valoarea 124.

 

Hai sa facem o tabla de sah (de 8x8) si sa o umplem, ca si in exemplul de mai sus, cu 1 si 0.

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var sir : array [1 .. 1000] of Integer;

tabla: array [1 .. 8, 1 .. 8] of byte;

i,j, n: Integer;

begin

for i := 1 to 8 do

for j := 1 to 8 do

tabla[i, j] := (i + j) mod 2;

 

for i := 1 to 8 do

begin

for j := 1 to 8 do

write(tabla[i,j]:2);

writeln;

end;

end.

 

Rezultatul acestei bucati de cod poate fi admirat in imaginea urmatoare:

 

So, cam asta ar fi si cu vectorii bidimensionali (matrice) ... cred ca v-am speriat degeaba ... puteti sa va dati jos centura de siguranta.

 

Vectorii cu mai mult de 2 dimensiuni se declara la fel (cu modificarile de rigoare), iar elementele din asemenea vectori sunt folositi la fel (din nou, cu modificarile de rigoare).

 

Atentie: Indiferent de numarul de dimensiuni al vectorului, indiferent de numarul de elemente pe care le contine, aveti grija sa nu incercati sa accesati pozitii care nu exista (cum ar fi pozitia 1001 sau 2000 in vectorul cu 1000 de elemente). In cel mai bun caz, valoarea citita de acolo va fi aleatoare. In cel mai rau caz veti primi un AV (access violation pentru necunoscatori) sau vreo eroare de rulare (runtime error).

 

Matrici patratice

 

Matricile patratice sunt acei vectori bidimensionali a caror numar de linii este egal cu numarul de coloane.

 

La acest tip de matrice putem vedea niste lucruri interesante, cum ar fi faptul ca numarul de elemente este egal cu latura2 (clar, nu?) ... sau ca are diagonale. Prin faptul ca are diagonale ma refer ca exista o serie de elemente ale matricii care determina respectivele diagonale.

 

Diagonalele unei matrici patratice sunt denumite: diagonala principala si diagonala secundara. Diagonala principala porneste din coltul din stanga sus si se termina in coltul din dreapta jos. Diagonala secundara incepe in coltul din dreapta sus si se termina in coltul din stanga jos.

 

In urmatoarea imagine puteti vedea rezultatul unui program care identifica elementele celor doua diagonale ale unei matrici patratice de 8x8. Diagonala principala este afisata cu rosu, iar cea secundara cu galben.

 

 

Codul programului care a scos acest rezultat este:

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var tabla: array [1 .. 8, 1 .. 8] of byte;

i, j: Integer;

begin

clrscr;

for i := 1 to 8 do

for j := 1 to 8 do

tabla[i, j] := (i + j + 1) mod 2;

 

for i := 1 to 8 do begin

for j := 1 to 8 do

begin

textcolor(LightGray);

 

if (i = j) then

TextColor(LightRed); {diagonala principala}

if (i = 8 - j + 1) then

TextColor(Yellow); {diagonala secundara}

 

write(tabla[i,j]:2);

end;

writeln;

end;

 

ReadLn;

end.

 

Daca ati analizat putin codul, ar trebui sa va fie clar ca un element din matrice face parte din diagonala:

principala, daca indecsii au aceeasi valoare (i = j)

secundara, daca indecsii se supun formulei urmatoare: i = n - j + 1, unde i, j sunt indecsii de linie, respectiv coloana, iar n este latura matricii patratice.

 

Daca nu ati inteles de ce, luati o foaie si un pix (sau creion sau orice care lasa semne pe hartie) si verificati formulele

 

Hai sa vedem cum aflam elementele din sectiuni demarcate de diagonale.

 

Aici, cu albastru, elementele de deasupra diagonalei principale.

 

 

Codul necesar:

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var tabla: array [1 .. 8, 1 .. 8] of byte;

i, j: Integer;

begin

clrscr;

for i := 1 to 8 do

for j := 1 to 8 do

tabla[i, j] := (i + j + 1) mod 2;

 

for i := 1 to 8 do begin

for j := 1 to 8 do

begin

textcolor(LightGray);

 

if (i = j) then {diagonala principala}

TextColor(LightRed);

 

if (i = 8 - j + 1) then {diagonala secundara}

TextColor(Yellow);

 

if (j > i) then {deasupra diagonalei principale}

TextColor(LightBlue);

 

write(tabla[i,j]:2);

end;

writeln;

end;

 

ReadLn;

end.

 

Dupa cum se vede, elementele de deasupra diagonalei principale au proprietatea ca indexul coloanei (j) este mai mare decat indexul liniei (i). Simplu.

 

Tot cu albastru, elementele de sub cele doua diagonale:

 

 

LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL

uses crt;

var tabla: array [1 .. 8, 1 .. 8] of byte;

i, j: Integer;

begin

clrscr;

for i := 1 to 8 do

for j := 1 to 8 do

tabla[i, j] := (i + j + 1) mod 2;

 

for i := 1 to 8 do begin

for j := 1 to 8 do

begin

textcolor(LightGray);

 

if (i = j) then {diagonala principala}

TextColor(LightRed);

 

if (i = 8 - j + 1) then {diagonala secundara}

TextColor(Yellow);

 

if (i > j) and (i > 8 - j + 1) then {sub cele doua diagonale}

TextColor(LightBlue);

 

write(tabla[i,j]:2);

end;

writeln;

end;

 

ReadLn;

end.

 

Proprietatea elementelor cu albastru este ca indicele liniei este mai mare decat indicele liniei SI este sub diagonala secundara (adica indexul de linie este mai mare decat numarul de linii, din care scadem indexul coloanei si adunam 1).

 

Restul sectiunilor si subsectiunilor determinate de diagonale le puteti afla si singuri, modificand programele de mai sus.

 

Sursa: http://www.bitcell.info/tutorial-pascal-lectia-4-vectori-tablouri-matrici-t54.html?sid=ba5880663f2c18ab18ed300345f06ba8

Edited by Cdorsu
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.