Primul articol a descris metode de lucru cu cel mai simplu tip de matrice - one-dimensional (liniar) matrice. În acest al doilea articol vom examina matrice multi-dimensionale. Practic, acesta va fi matrice aproximativ două-dimensionale. Dar aceste exemple extrapolate cu ușurință la rețele de orice dimensiune. Ca și în primul articol, vom lua în considerare doar matrice în C stil / C ++, fără utilizarea de oportunități STL.
clasice ale genului
Dacă deschidem clasic de lucru «C Programming Language“, de Brian Kernighan și Dennis Ritchie. Am citit că „În C, există posibilitatea de a lucra cu matrice rectangulară multi-dimensionale, deși, în practică, ele sunt utilizate mult mai puțin frecvent decât matrici de pointer.“ C ++ este moștenit aproape în întregime de lucru cu matrice multidimensionale, predecesorul său.
Definiția matrice automate multi-dimensionale
În această secțiune, voi folosi uneori termenul „matrice“ ca sinonim pentru termenul „matrice bidimensională.“ dreptunghiular matrice bidimensională de numere implementează într-adevăr conceptul matematic de „matrice“ C / C ++. Cu toate acestea, în general, un tablou bidimensional - conceptul este mult mai largă decât matricea, deoarece aceasta nu poate fi dreptunghiular, nu numeric.
Definiția matrice automate multi-dimensionale este aproape identică cu definiția de matrice unidimensionale (ceea ce a fost discutat în primul articol), cu excepția faptului că în loc de o singură dimensiune poate fi de mai multe:
Acest exemplu definește o matrice bidimensională de 3 rânduri de valori de tip int 5 în fiecare rând. Total 15 valori int.
In al doilea exemplu definește o matrice tridimensională, care cuprinde trei matrici, fiecare dintre care este compus din 5 rânduri de două valori de tip int în fiecare rând.
Se înțelege că tipul de date conținute într-o matrice multidimensionale poate fi orice.
Termenul «C-matrice“ va fi utilizat în timpul expunerii în urma acestor matrice multidimensionale. care le-ar distinge de alte tipuri de matrice.
iniţializarea
Cu statice (determinată la compilare) valorile de inițializare C-matrice sunt listate în ordinea specifica dimensiunile (index) în definiția matrice. Fiecare nivel (index), cu excepția cel mai mic, o matrice multidimensională este o pereche de bretele. Valorile mezina indicelui sunt separate prin virgulă:
În exemplul prezentat o inițializare statică dreptunghiular matrice. Intreaga lista valorilor de inițializare închise în paranteze. Valorile pentru fiecare dintre cele 3 rânduri sunt închise într-o pereche de bretele, valorile pentru fiecare dintre cele 5 coloane pentru fiecare linie sunt listate separate prin virgulă.
Dacă există un initializare, cel mai stânga de matrice poate fi omisă. În acest caz, compilatorul va determina dimensiunea, pe baza listei de inițializare.
Completarea unui tablou de valori
O matrice multidimensionale este populat cu valori folosind bucle imbricate. Și, de regulă, numărul de cicluri de aceleași ca și dimensiunea matrice:
În acest exemplu, fiecare element de matrice este setat, prima cifră care indică numărul rândului și al doilea număr - numărul coloanei pentru această valoare (numerotate de la 1).
matrice de valori de ieșire la consolă
Continuând exemplul anterior, puteți scrie:
Ca urmare, următoarea ieșire la consolă:
puteți scrie cod pentru matrice tridimensională, folosind aceleași metode:
Aici, atribui o valoare unui element de matrice și de ieșire la ciclurile de console apar într-un singur grup.
Locație în memorie
Pentru multidimensională C-matrice este alocat un singur bloc de memorie dimensiune cerută: razmer_massiva1 razmer_massiva2 *. * Razmer_massivaN * sizeof (tip_elementa_massiva).
Valorile sunt aranjate în serie. Cel mai din stânga index variază mai lent. Ie pentru matrice tridimensională este mai întâi valorile plasate pentru primul (index 0) al matricei, apoi pentru a doua, etc. Valorile pentru matrici sunt aranjate linie cu linie (vezi. Inițializarea statică a matrice de mai sus).
Numele (ID) al multidimensional C-matrice este un pointer la primul element al șirului (precum și pentru tablouri unidimensionale)
În cazul în care codul ultimul exemplu, o mică schimbare:
a stabilit un punct de întrerupere pe retur și căutați sub o memorie de depanator alocat sub Ary variabilă. se va observa că valorile situate într-o memorie, secvențial în creștere:
Ultimul fragment oferă acces la valorile matrice bidimensional ca o matrice unidimensională. Civilizat soluție se realizează prin unirea.
Din cele două exemple prezentate mai sus, rezultă că lucrul cu o matrice bidimensională sau multi-dimensional (așa cum este definită printr-un nivel mai ridicat de abstractizare) este tehnic posibil pentru a aranja o dimensiune corespunzătoare one dimensionale matrice:
Aceasta tehnica este destul de comună. Beneficiul său este faptul că matrice Ary [DIM1 * DIM2] nu trebuie să fie recuperate în mod automat. Acesta poate fi selectat și dinamic. Dar este privit în mod logic, ca un C-matrice.
gemeni nonnative
Acum, ia în considerare un loc de muncă cu matrice „dinamic“ multi-dimensionale, de exemplu, tablouri, memoria alocata dinamic.
Crearea și distrugerea matricele dinamice multi-dimensionale
În general, lucrul cu astfel de matrice este după cum urmează:
(1) Pentru a avea acces la un tablou bidimensional este declarat variabilă ary de tip pointer la un pointer la un tip (în acest caz, un pointer la un pointer la un int).
(2) Variabila este inițializată de către operator nou. care alocă memorie pentru o serie de indicii pentru a int.
(3) În fiecare element de buclă a șirului de indicii inițializate nou operator. care alocă memorie pentru o matrice int.
Eliberator apare strict în ordinea inversă: Șirurile mai întâi distruse de int. și apoi a distrus o serie de indicii.
Lucrul cu sintaxa dinamică matrice multidimensionale este identică pentru a lucra cu multidimensional C-matrice.
Exemplu de cod pentru matrice tridimensională:
În cazul în care câinele scotoci
Lucrul cu sintaxa dinamică matrice multidimensionale este identică pentru a lucra cu multidimensional C-matrice. (Pentru a cita secțiunea anterioară.) Sintactic, da - dar între aceste matrice, există o diferență profundă, care începe programatorii de multe ori uita.
În primul rând, cantitate diferită de memorie alocată pentru matrice dinamică.
Dacă vom calcula cât de mult de memorie vor fi alocate matrice bidimensională în exemplul de mai sus, obținem: un prim operator de memorie pentru noi alocat 3 indicii în al doilea operator de noul ciclu de memorie alocat de trei ori pentru elemente de tip 5 int. Ie Se întâmplă că memoria alocată pentru tipul int valorile 15 și 3 pe valorile pointer tip int. Pentru C-compilator de matrice a fost alocată memorie doar 15 valori int. (Tot felul de nivelare și alte optimizare nu contează!)
În al doilea rând, memoria alocată pentru o gamă dinamică nu este continuă. În consecință, hack №1 (tratament cu matrice bidimensionale ca one-dimensional) nu va funcționa.
În al treilea rând, transferul de matrice multidimensionale la funcții și de lucru cu ei vor fi diferite pentru tablouri dinamice și C-matrice.
matrice dinamică multi-dimensional este implementat ca o serie de indicii pentru matrice de valori care, la rândul lor, pot fi, de asemenea, indicii pentru matrice. Veriga finală din acest lanț va fi întotdeauna o matrice cu valorile tipului țintă.
matrice dinamică multi-dimensionale NU este un C-matrice.
In mod paradoxal, care este cel mai apropiat de aceste gemeni rodstvennichki non-nativi este hack №2, pune în aplicare operațiunea cu o matrice multidimensionale înseamnă un tablou dimensional (vezi pct. Khaki). Toate cele trei dintre diferențele de mai sus sunt irelevante pentru el.
Este demn de remarcat faptul că o serie de indicii pentru matricele - o structură mai flexibilă decât matrice dimensional-C. De exemplu, pentru o serie de indicii la dimensiunea de matrice de matrice pot fi diferite, sau un fel de matrice pot fi absente. Cel mai comun exemplu este un „linii solide“, adică, matrice de indicii pentru tip matrice char (exemplu - vezi secțiunea următoare.).
Din nou despre siguranță
Din cele de mai sus, este necesar să se facă distincția clară matrice multi-dimensionale de tip C
pe matrice de indicii pentru matrice.
Uneori, diferențele externe sunt neglijabile. De exemplu, C-string - un tablou unidimensional de elemente de tip char. de încheiere octet nul. Cum să pună în aplicare o serie de siruri de caractere?
Acesta este - un exemplu de definire și inițializarea bidimensională C-matrice
Și aici este definit și inițializată unidimensional (!) Array de indicii pentru matrici de elemente char.
Și, în sfârșit, mai mult de un avertisment.
Deoarece matrice multidimensionale ocupă C-de obicei, o cantitate mare de memorie, acestea ar trebui să fie cu precauție extremă în funcții de declarare, inclusiv main (). Și, cu precauție, în gradul n-lea în funcții recursive. Puteți obține cu ușurință o stivă de preaplin și, ca rezultat, un program de terminare anormală.
matrice multi-dimensionale atunci când se lucrează cu funcții
Deoarece multidimensionale C-matrice și matrice multidimensionale dinamice - două tipuri foarte diferite de date, chiar și atunci când se lucrează cu abordarea funcții vor fi diferite.
Funcția de transfer în multidimensional C-matrice
Funcția primește C-matrice ca un parametru poate arăta după cum urmează:
Forma (1) - cele mai comune.
Forma (2). Atunci când transmiterea multidimensională funcția C-matrice nu se poate specifica lungimea cea mai din stânga dimensiune. Compiler pentru calcularea accesarea unei matrice, nu este nevoie de această informație.
C-return matrice multidimensională a funcției ca rezultat al mijloacelor convenționale este imposibilă.
Funcția de transfer într-o matrice dinamică multidimensional
Deoarece matrice dinamică multi-dimensional este implementat ca un tablou unidimensional de indicii, apoi, respectiv, și atunci când se lucrează cu funcții utilizează aceeași abordare ca și pentru matrice unidimensională, așa cum este descris în primul articol. până la tipuri de date.
De exemplu, - codul complet al programului, care arată funcționarea unui tablou dinamic bidimensional cu ajutorul funcțiilor.
In primul articol am scris, că „memoria este alocată o singură funcție, și pentru a elibera cealaltă - o idee rea, plină de erori.“ Prin urmare, luați în considerare acest exemplu ca o demonstrație funcționează numai cu funcții și matrici de pointer.
În timp ce pe de altă parte. Pe de altă parte, o abordare foarte similară este frecvent utilizat în clase în cazul în care o resursă (în acest caz, fiica) este capturat într-o singură funcție (Designer) și eliberate într-un alt (destructor). Dar, în cazul claselor, încapsulare, securitatea este furnizat date critice și menținerea unei stări coerente a metodelor de instanță a clasei.
O serie de indicii folosite în fiecare program, care poate primi informații de la linia de comandă (sau apelul său pe sistemul de operare). Una dintre formele clasice de funcție principală () este după cum urmează:
Argumentele funcției sunt numărul de rânduri argc (dimensiunea de matrice pointer) și o serie de indicii pentru siruri de caractere - argv. Ie argv - este o serie de indicii pentru matrice de valori char.
Poate asta e tot ce am vrut să-ți spun în acest articol. Sper că cineva consideră că este util pentru ei înșiși.
Că el să rămână cu voi sfinți apostoli și Bjarne-l! ;-)