By Matei George Decebal
O matrice este o colecție de elemente de același tip plasate în locații de memorie adiacente care pot fi referite individual prin utilizarea unui index la un identificator unic. Cinci valori de tip int pot fi declarate ca o matrice fără a fi nevoie să declare cinci variabile diferite (fiecare cu propriul său identificator). De exemplu, un tablou întreg de cinci elemente foo poate fi reprezentat logic ca; . .
unde fiecare panou gol reprezintă un element al matricei. În acest caz, acestea sunt valori de tip int. Aceste elemente sunt numerotate de la 0 la 4, 0 fiind primul, iar 4 fiind ultimul; În C++, indexul primului element de matrice este întotdeauna zero. După cum era de așteptat, o matrice n trebuie declarată înainte de utilizare. O declarație tipică pentru o matrice în C++ este:
tipul numenele [elementele];
unde type este un tip valid (cum ar fi int, float ...), name este un identificator valid și câmpul elemente (care este întotdeauna cuprins între paranteze drepte []), specifică dimensiunea matricei. Astfel, matricea foo, cu cinci elemente de tip int, poate fi declarată astfel:
int foo [5];
În mod implicit, sunt lăsate neinițializate. Aceasta înseamnă că niciunul dintre elementele sale nu este setat la o valoare anume; conținutul lor este nedeterminat în punctul în care matricea este declarată. Inițializatorul poate avea nici măcar valori, doar acolade:
int baz [5] = { };
Aceasta creează o matrice de cinci valori int, fiecare inițializată cu o valoare de zero:
Dar, elementele dintr-o matrice pot fi inițializate în mod explicit la valori specifice atunci când este declarată, prin includerea acelor valori inițiale între acolade {}. De exemplu:
int foo [5] = { 16, 2, 77, 40, 12071 };
Numărul de valori dintre acolade {} nu trebuie să fie mai mare decât numărul de elemente din matrice. De exemplu, în exemplul de mai sus, foo a fost declarat având 5 elemente (după cum este specificat de numărul cuprins între paranteze drepte, []), iar parantezele {} au conținut exact 5 valori, câte una pentru fiecare element. Dacă sunt declarate cu mai puțin, elementele rămase sunt setate la valorile implicite (ceea ce pentru tipurile fundamentale, înseamnă că sunt umplute cu zerouri). De exemplu:
int bar [5] = { 10, 20, 30 };
Va crea o matrice ca aceasta:
Atunci când este prevăzută o inițializare a valorilor pentru o matrice, C++ permite posibilitatea de a lăsa parantezele pătrate goale[]. În acest caz, compilatorul va prelua automat o dimensiune pentru matrice care se potrivește cu numărul de valori incluse între acolade {}:
int foo [] = { 16, 2, 77, 40, 12071 };
După această declarație, matricea foo va avea cinci int lung , deoarece am furnizat cinci valori de inițializare. În cele din urmă, evoluția C++ a dus la adoptarea inițializării universale și pentru matrice. Prin urmare, nu mai este nevoie de semnul egal între declarație și inițializator. Ambele afirmații sunt echivalente:
int foo[] = { 10, 20, 30 };
int foo[] { 10, 20, 30 };
Aici, numărul matricei n este calculat de către compilator utilizând formula n= #of initializes/size of(int). Matricele statice și cele declarate direct într-un spațiu de nume (în afara oricărei funcții), sunt întotdeauna inițializate. Dacă nu este specificat niciun inițializator explicit, toate elementele sunt inițializate implicit (cu zerouri, pentru tipurile fundamentale).
TValorile oricăruia dintre elementele dintr-o matrice pot fi accesate la fel ca valoarea unei variabile obișnuite de același tip. Sintaxa este: nume[index]
Urmând exemplele anterioare în care foo avea 5 elemente și fiecare dintre acele elemente era de tip int, numele care poate fi folosit pentru a face referire la fiecare element este următorul:
De exemplu, următoarea instrucțiune stochează valoarea 75 în al treilea element al lui foo:
foo [2] = 75;
și, de exemplu, următoarele copiază valoarea celui de-al patrulea element al lui foo într-o variabilă numită x:
x = foo[3];
Prin urmare, expresia foo[2] sau foo[4] este întotdeauna evaluată la un int. Observați că al treilea element al lui foo este specificat foo[2], al doilea este foo[1], deoarece primul este foo[0]. Ultimul element este, prin urmare, foo[4]. Dacă scriem foo[5], am accesa al șaselea element al lui foo și, prin urmare, am depăși efectiv dimensiunea matricei.
În C++, este corect din punct de vedere sintactic să depășești intervalul valid de indici pentru o matrice. Acest lucru poate crea probleme, deoarece accesarea elementelor în afara intervalului nu provoacă erori la compilare, dar poate provoca erori în timpul de execuție. Motivul pentru care acest lucru este permis deoarece verificarea indexului încetinește execuția programului. În acest moment, este important să se poată distinge clar între cele două utilizări pe care parantezele [] le au legate de matrice. Ei îndeplinesc două sarcini diferite: una este de a specifica dimensiunea matricelor atunci când sunt declarate; iar al doilea este de a specifica indici pentru elementele matrice concrete atunci când sunt accesate. Nu confundați aceste două posibile utilizări ale parantezelor [] cu matrice.
int foo[5];
foo[2] = 75;
Principala diferență este că declarația este precedată de tipul elementelor, în timp ce accesul nu este.
Alte operații valide cu matrice:
foo[0] = a;
foo[i] = 75;
b = foo [i+2];
foo[foo[i]] = foo[i] + 5;
Matricele multidimensionale pot fi descrise ca „matrice de matrice”. De exemplu, o matrice bidimensională poate fi imaginată ca un tabel bidimensional format din elemente, toate având același tip de elemente.
Tabelul reprezintă o matrice bidimensională de 3 la 5 elemente de tip int. Sintaxa C++ pentru aceasta este
int Table [3][5];
și, de exemplu, modalitatea de a face referire la al doilea element pe verticală și pe al patrulea pe orizontală într-o expresie ar fi:
Table[1][3]
(rețineți că indicii de matrice încep întotdeauna cu zero)
Matricele multidimensionale nu sunt limitate la doi indici (adică, două dimensiuni). Ele pot conține oricât de mulți indici sunt necesari. Deși aveți grijă: cantitatea de memorie necesară pentru o matrice crește exponențial cu fiecare dimensiune. De exemplu:
char century [100][365][24][60][60];
Declara o matrice cu un element de tip char pentru fiecare secunda dintr-un secol. Aceasta înseamnă mai mult de 3 miliarde de char! Deci această declarație ar consuma mai mult de 3 gigaocteți de memorie! Și o astfel de declarație este foarte improbabilă și subliniază utilizarea ineficientă a spațiului de memorie. La final, tablourile multidimensionale sunt doar o abstractizare pentru programatori, deoarece aceleași rezultate pot fi obținute cu o matrice simplă, prin înmulțirea indicilor acesteia:
int Table [3][5]; // este echivalent cu:
int Table [15]; // (3 * 5 = 15)
Cu singura diferență că în cazul tablourilor multidimensionale, compilatorul își amintește automat adâncimea fiecărei dimensiuni imaginare. Următoarele două bucăți de cod produc exact același rezultat, dar una folosește o matrice bidimensională, în timp ce cealaltă folosește o matrice simplă:
const int WIDTH = 5;
const int HEIGHT = 3;
int Table [HEIGHT][WIDTH];
int n,m;
int main ()
{
for (n=0; n< HEIGHT; n++)
for (m=0; m< WIDTH; m++)
{
Table[n][m]=(n+1)*(m+1);
}
}
const int WIDTH = 5;
const int HEIGHT = 3;
int Table [HEIGHT][WIDTH];
int n,m;
int main ()
{
for (n=0; n< HEIGHT; n++)
for (m=0; m< WIDTH; m++)
{
Table[n*WIDTH+m]=(n+1)*(m+1);
}
}
Niciunul dintre cele două fragmente de cod de mai sus nu produce nicio ieșire pe ecran, dar ambele atribuie valori blocului de memorie numit jimmy în următorul mod:
Rețineți că codul folosește constante numite pentru lățime și înălțime, în loc să le folosească direct valorile numerice. Acest lucru oferă codului o lizibilitate mai bună și permite modificările în cod să fie făcute cu ușurință într-un singur loc.
int mat[3][5], row, col ;
for (row = 0; row < 3; row++)
for (col = 0; col < 5; col++)
cin >> mat[row][col];