Ero sivun ”C” versioiden välillä
Poistettu sisältö Lisätty sisältö
Kirjoitettu moniulotteiset taulukot uusiksi, koska alkuperäinen oli virheellinen. |
|||
Rivi 391:
==== Dynaamiset ====
Pointteritaulukko on huomattavasti staattista taulukkoa joustavampi ratkaisu, mutta myös merkittävästi hankalampi luoda. Taulukko ei myöskään tuhoudu automaattisesti lohkon päätteeksi, vaan se täytyy itse vapauttaa. Staattisesta moniulotteisesta taulukosta poiketen, pointteritaulukko voidaan helposti välittää funktion argumenttina, tietämättä sen kokoa ennalta. Seuraavassa esimerkki täysin dynaamisesta moniulotteisesta taulukosta:
#include <stdio.h>
// Varataan ulommaisin taulukko (ensimmäinen indeksi), sisältää pointtereita sisätaulukoihin▼
#include <stdlib.h>
int** taulukko = malloc(3 * sizeof(int*));▼
for (size_t i = 0; i < 3; ++i) {▼
// Varataan sisätaulukko (toinen indeksi), sisältää numeroita▼
// Alustetaan taulukon solut vastaavilla arvoilla kuin staattisella taulukolla edellä▼
putchar('\n');▼
for (size_t j = 0; j < 4; ++j) taulukko[i][j] = (i + 1) * 10 + j + 1;▼
}▼
}
// Vapautetaan taulukolle varattu muisti▼
for (size_t i = 0; i < 3; ++i) free(taulukko[i]);▼
taulukko = NULL; // Jottei vahingossa käytettäisi jo vapautettua muistia▼
int** array_construct(size_t dim1, size_t dim2) {
Edellä olevassa esimerkkikoodissa mallocin paluuarvoja ei tarkistettu, mutta oikeassa koodissa pitää aina mallocin kutsumisen jälkeen tarkistaa palauttiko kutsu NULL:n ja suorittaa vaadittavat siivoustoimenpiteet (esim. jo varatun muistin vapautus).▼
▲ // Varataan sisätaulukko (toinen indeksi), sisältää numeroita
array[i] = malloc(dim2 * sizeof(int));
▲ // Alustetaan taulukon solut vastaavilla arvoilla kuin staattisella taulukolla edellä
}
}
void array_destruct(int** array) {
free(array);
}
int main(void) {
int** array = array_construct(3, 4);
// ...
print(array, 3, 4);
// Kerrotaan oikeassa alakulmassa olevan alkion arvo sadalla:
array[2][3] *= 100;
// ...
array_destruct(array);
// ...
}
▲Edellä olevassa esimerkkikoodissa mallocin paluuarvoja ei tarkistettu, mutta oikeassa koodissa pitää aina mallocin kutsumisen jälkeen tarkistaa palauttiko kutsu NULL:n ja tällöin suorittaa vaadittavat siivoustoimenpiteet (esim. jo varatun muistin vapautus) ennen funktiosta poistumista.
Täysin dynaamisessa pointteritaulukossa rivien ei tarvitse olla yhtä pitkiä, eli loopin sisällä oltaisiin voitu tehdä malloc((i + 1) * sizeof(int)), jolloin ensimmäisellä rivillä olisi yksi alkio, toisella kaksi, jne. Rivien kokoa voi muuttaa (realloc) ilman että muulle taulukossa olevalle tiedolle tarvitsee tehdä mitään ja myös rivien lisäys ja poisto hoituu kevyesti rivipointtereita siirtelemällä (sisällä olevaa tietoa ei tarvitse siirtää esim. lisättäessä uusi rivi taulukon alkuun).
Rivi 418 ⟶ 443:
Edellisessä esimerkikssä taulukko t olisi yhtä hyvin voinut olla staattinen kaksiulotteinen taulukko, koska sellaisen sisäinen rakenne on identtinen yksiulotteisen taulukon kanssa.
▲ void print(int** taulukko, size_t dim1, size_t dim2) {
▲ for (size_t j = 0; j < dim2; ++j) printf("%d ", taulukko[i][j]);
▲ putchar('\n');
▲ }
▲ }
== Merkkijonot ==
|