Tietorakenteet¶
Tietorakenne (engl. struct, suomeksi rakenne, tietue, jne..) on usean muuttujan kokoelma ryhmitelttynä loogiseksi yksiköksi. Tietorakenteen jäsenet voivat C-kielessä olla mitä tahansa muuttujatyyppejä. Tällä tavoin voidaan pakata toisiinsa liittyviä tietoja yhteen, esimerkiksi (tällä kurssilla) tiedonsiirron viestirakenteen määrittely. Tietorakenteet ovat erittäin yleinen ohjelmoinnin konsepti.
C-kielessä tietorakenne määritellään
struct
sanalla, jonka syntaksi on:struct nimi { jäsenmuuttujien_esittely; } mahdollinen_rakennemuuttujan_esittely;
Esimerkiksi.
struct point {
int x;
int y;
} min_pt, max_pt; // Esitellään valmiiksi kaksi point-tyypin globaalia muuttujaa
struct rect {
struct point max;
struct point min;
struct point all_points[10];
}; // määrittely pitää aina lopettaa puolipisteeseen, oli esittelyjä tai ei
Tässä luodaan ensin
point
-niminen tietorakenne, jossa on kaksi jäsentä x
ja y
, sekä esitellään kaksi point-tyypin muuttujaa min_pt
ja max_pt
. Sitten luodaan rect
-tietorakenne, jonka jäseninä ovat point-tyypiset max
, min
ja point-tyypin taulukko all_points[10]
. Rakennetaulukon alkiota voidaan käsitellä indeksin avulla, kuten muissakin taulukoissa, esimerkiksi all_points[1]
.Määrittelyssä ei alusteta rakenteen muuttujia, se pitää tehdä erikseen. Syy on se, että määrittelyssä luomme uuden tietorakenteen, jota koodissa voidaan käyttää kuin uutta muuttujatyyppiä, emmekä vielä siis esittele uuden tietorakenteen mukaisia muuttujia.
Esittely ja alustus¶
Esittely ja alustus voidaan tehdä kuten minkä tahansa muuttuja, mutta yleensä jokaiselle jäsenmuuttujalle erikseen.
struct point pt1; // Ei alustusta
struct point pt1[10]; // Taulukko, jossa 10 rakennetta, ei alustusta
struct point pt2 = { 100, 200 }; // Nyt esitellään ja alustetaan: pt2.x=100 ja pt2.y = 200
struct point pt2; // Tai näin..
pt2.x = 100;
pt2.y = 200;
Jos tietorakenteen jäsen on merkkijono, alustaessa ja sijoittaessa se täytyy kopioida jäsen-muuttujaan. Tähän string.h kirjasto tarjoaa esim.
strncpy
-funktion. Merkkijonon pituus saadaan myös saman kirjaston funktiolla strlen
.struct henkilo {
char osoite[10];
} kaveri;
char kaveri_osoite[] = "Tie 1";
strncpy(kaveri.osoite, kaveri_osoite, strlen(kaveri_osoite));
Tietorakenteita voi sijoittaa toisiinsa
=
-operaattorilla. Tällöin jokainen jäsen kopioidaan. min_pt = max_pt;
(Huomataan, että jos jäsen on osoitin, niin sen arvo kopioidaan sellaisenaan. Ts. molemmat osoittimet osoittavat samaan muistiosoitteeseen. Jos halutaan toisen rakenteen osoittimen osoittavan uuteen muistiosoitteen, jossa on sama sisältö, täytyy se kopioida memcpy-funktiolla (string.h) ja ensin huolehtia että uusi muistialue on esitelty.)
Käyttö¶
Koodissa rakenteen käyttöön tarvitaan kaksi uutta operaattoria.
Rakenteen jäseniä käsitellään kuin mitä tahansa muuttujia
.
-operaattorilla.struct point {
int x;
int y;
} min_pt;
min_pt.x = 0;
min_pt.y = 0;
struct rect {
struct point max;
struct point min;
struct point all_points[10];
} laatikko;
// Tässä pitää huomata, että laatikossa on max-niminen
// jäsen, jonka jäseniinn x ja y halutaan sijoittaa arvot
laatikko.max.x = 320;
laatikko.max.y = 200;
printf("%d,%d", laatikko.max.x, laatikko.max.y);
Jos meillä on osoitin rakenteeseen, käytämme operaattoria
->
.struct point *min_pt;
struct rect *laatikko;
min_pt->x = 0;
min_pt->y = 0;
// Tässä pitää huomata, että laatikko-muuttuja on osoitin,
// mutta sen jäsen max ei ole osoitin, joten sille pisteoperaattori!
laatikko->max.x = 320;
laatikko->max.y = 200;
printf("%d,%d", laatikko->max.x, laatikko->max.y);
Funktion parametreinä tietorakenteita käytetään tyypillisesti osoittimien avulla.
Esimerkki. Tietorakenteiden vertailu ei välttämättä onnistu, ellei sitä varten toteuta omaa funktiotaan, jossa vertaillaan jäseniä valitulla kriteereillä.
struct point *palauta_isompi(struct point *a, struct point *b) {
// Hox! palautetaan osoitin jompaankumpaan
if (a->x > b->x) {
return a;
} else {
return b;
}
}
int main() {
struct point eka, toka;
struct point *isompi;
...
// Hox! Tässä nyt argumentiksi tietorakenteen osoite
isompi = palauta_isompi(&eka, &toka);
...
}
Omat muuttujatyypit¶
Tässä materiaalissa on tuodaan esiin tapa luoda omia muuttujatyyppejä, eli enum (seuraava materiaali..) ja yllä struct. Okei, varsinaisestihan tässä ei luoda uusia muuttujatyyppejä, mutta uudelleennimetään tai kootaan perusmuuttujatyyppejä. Minkä tahansa muuttujatyypin uudelleennimeämiseen C-kielessä on sana
typedef
. Tällä tavoin esitellyissä muuttujissa ei ole mitään erityistä, ne toimivat täsmälleen samoin kuin vastaavat perusmuuttujatyypit.
Esimerkiksi.
typedef uint16_t Length;
Length max_len = 100;
printf("%d\n"; max_len);
typedef char *String; // Uudelleennimetään osoitin
String viesti = &toinen_merkkijono;
printf("%s\n"; viesti);
typedef
:iä voidaan käyttää esimerkiksi alustalta toiselle siirrettävän koodin luomiseen. Eli luodaan ohjelmaan omat muuttujatyypit, jolloin vain niiden määritellyt saatetaan joutua muuttumaan, kun koodi siirretään uudelle alustalle. Lopuksi¶
Kurssin sulautetun laitteen ohjelmoinnissa tulemme käyttämään sekä struct:eja että typedef:llä uudelleennimettyjä muuttujatyyppejä.
Anna palautetta
Kommentteja materiaalista?