Tietorakenteet¶
Tietorakenne (engl. struct, suomeksi rakenne, tietue, jne..) on usean muuttujan kokoelma ryhmitelttynä loogiseksi yksiköksi. Tietorakenteella voidaan siis paketoida toisiinsa liittyviä tietoalkioita yhteen, esimerkiksi nyt tietokannan eri tietueet tai (tällä kurssilla) tiedonsiirron viestirakenteen eri parametrien määrittely tai SensorTagin tehtävien alustusparametrit. Toki tietorakenteet ovat yleinen ohjelmoinnin konsepti.
Tietorakenteen jäsenet voivat C-kielessä olla mitä tahansa muuttujatyyppejä. C-kielessä tietorakenne määritellään
struct
sanalla, jonka syntaksi on:struct nimi { jäsenmuuttujan_esittely; toisen_jäsenmuuttujan_esittely; ... } mahdollinen_tietorakennemuuttujan_esittely;
Esimerkiksi.
struct point {
int x; // jäsen x
int y; // jäsen y
} min_pt, max_pt; // Esitellään valmiiksi kaksi struct point-tyypin muuttujaa
struct rect {
struct point max; // jäsenenä nyt tietorakenne point nimellä max
struct point min;
struct point all_points[10]; // taulukon alkiona pointi-tyypin tietorakenteet
}; // 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¶
Tietorakenteen esittely ja alustus voidaan tehdä kuten minkä tahansa muuttujan, mutta alustus pitää (yleensä) tehdä jokaiselle jäsenmuuttujalle erikseen.
struct point {
int x;
int y;
}
// tietorakennemuuttujan esittely
struct point resolution;
// jäsenten alustus
resolution.x = 320;
resolution.y = 200;
}
struct point resolution2 = { 176, 184 }; // esittely ja alustus samassa lauseessa
struct point resolutions[10]; // Taulukko, jossa 10 tietorakennetta, ei alustusta
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
.// tietorakenteen ja muuttujan esittely
struct koulu {
char kadunnimi[80];
uint8_t osoitenumero;
} yliopisto;
// jäsenten alustus
char tietotalo[] = "Erkki Koiso-kanttilan katu";
strncpy(yliopisto.kadunnimi, tietotalo, strlen(tietotalo));
yliopisto.osoitenumero = 3;
Tietorakenteita voi sijoittaa toisiinsa
=
-operaattorilla. Tällöin jokainen jäsen kopioidaan. min_pt = max_pt;
Hox! Jos jäsen on osoitin, niin sen arvo eli muistipaikan osoite kopioidaan sellaisenaan. Ts. molemmat osoittimet osoittavat samaan muistiosoitteeseen. Jos halutaan toisen rakenteen osoittimen osoittavan uuteen muistiosoitteen, jossa on sama sisältö, täytyy sisältö kopioida (esim. memcpy-funktio, string.h) toiseen muistialueeseen.
Käyttö¶
Koodissa rakenteen käyttöön tarvitaan kaksi uutta operaattoria.
1. 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;
// Nyt laatikossa on max-niminen jäsen
// jonka jäseniin x ja y halutaan sijoittaa arvot
laatikko.max.x = 320;
laatikko.max.y = 200;
// Viittaus jäseniin pisteoperaattorin avulla
printf("%d,%d", laatikko.max.x, laatikko.max.y);
2. Myös osoittimen esittely tietorakenteeseen onnistuu, jäsenten osoittamiseen käytämme operaattoria
->
.struct point *min_pt;
// Nyt viittaus jäseniin
min_pt->x = 0;
min_pt->y = 0;
struct rect *laatikko;
// Tässä pitää huomata, että laatikko-muuttuja on osoitin,
// mutta 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, kääntäjä esimerkiksi vertailisi vain tietorakenteiden muistiosoitteita eikä jäsenten arvoja, ellei sitä varten toteuta omaa funktiotaan, jossa vertaillaan jäseniä.
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¶
C-kieli tarjoaa tietorakenteiden lisäksi mahdollisuuden esitellä omia muuttujatyyppejä. 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.
// Korvataan tyyppi uint16_t nimellä Length
typedef uint16_t Length;
// Esitellään ja alustetaan "Length"-tyypin muuttuja
Length max_len = 100;
// Tulostetaan "Length"-tyypin muuttaja
printf("%d\n", max_len);
// Uudelleennimetään merkkijono-osoitin
typedef char *String;
// Esitellään ja alustetaan
String viesti = &toinen_merkkijono;
// Tulostetaan "String"-tyypin merkkijono
printf("%s\n", viesti);
Usein
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?