Tietorakenteet ja algoritmit Useampitasoiset ADT:t Käytetään esimerkkiohjelmaa Ratkaisuyritys 1 Ratkaisuyritys 2 Lopullinen ratkaisu Lopullisen ratkaisun toteutusyritys Lopullisen ratkaisun oikea toteutus Ympyrän kuvauksen hierarkiakaavio 1
Useampitasoinen abstraktiomalli Asian monimutkaistuessa abstraktiomallissa tarvitaan useampia tasoja, jotta asia voidaan hallita (kts sivu 5 osassa 1). Käytämme taas esimerkkiohjelmaa asian valaisemiseksi. 2
Esimerkkiohjelman tehtäväkuvaus Ympyräohjelman tehtäväkuvaus Kirjoita ohjelma, jolle syötetään ympyrän määrittelevät tiedot. Ohjelma laskee ja tulostaa ympyrän pinta-alan ja myös syötetyt ympyrän tiedot. 3
Ensimmäinen ratkaisuyritys int main(void) { float cpx, cpy, r, area; printf( Anna keskipisteen x ja y : ); scanf( %f%f, &cpx, &cpy); printf( Anna säde : ); scanf( %f, &r); area = PII * r *r; printf( Ympyrän ala on %f\n, area); } Ylemmän tason käsitteitä ei näy ollenkaan. Mitkä tiedot määräävät ympyrän? printf( Keskipiste on (%f, %f). Säde on %f\n, cpx, cpy, r); return 0; 4
Toinen ratkaisuyritys Ympyrän määrittelevät tiedot ovat keskipiste ja säde (ei 3 lukua). Hyödynnetään aikaisemmin kehitetty ADT point keskipisteen esittämisessä. int main(void) { Tpoint cp; float r, area; read_point(&cp, Anna keskipiste : ); printf( Anna säde : ); scanf( %f, &r); area = PII * r *r; printf( Ympyrän ala on %f\n, area); print_point(&cp, Ympyrän keskipiste ); return 0; } Tämä on parempi ratkaisu. Mutta mitä tehtävässä pitikään tehdä ja mitä asiaa käsitellä? 5
Lopullinen ratkaisu Tehtävässä piti lukea ympyrän tiedot, laskea ympyrän ala jne. Näitä ei näy edellisen sivun ratkaisussa. void main(void) { Tcircle c; float area; read_circle(&c); area = circle_area(&c); print_circle(&c); printf("%f", area); } 6
Lopullisen ratkaisun toteutusyritys typedef struct { float kpx; float kpy; Ei hyvä! float r; } Tcircle; void read_circle(tcircle* c, const char* prompt); void print_circle(const Tcircle* c, const char* prompt); float circle_area(const Tcircle* c); jne Tällä voisi toteuttaa edellisen sivun lopullisen ratkaisun, mutta... Ei hyödynnetä (uudelleen käytetä) jo kerran tehtyä pistettä keskipisteen esittämiseen. 7
Lopullisen ratkaisun oikea toteutus 1/2 typedef struct { Tpoint cp; float r; } Tcircle; void read_circle(tcircle* c, const char* prompt); void print_circle(const Tcircle* c, const char* prompt); float circle_area(const Tcircle* c); jne Nyt hyödynnetään (uudelleenkäytetään) jo kerran tehtyä pistettä keskipisteen esittämiseen. 8
Lopullisen ratkaisun oikea toteutus 2/2 Toteutetaan malliksi yksi ADT circlen käyttöfunktioista: void read_circle(tcircle* c, const char* prompt) { printf( %s, prompt); read_point(&c->cp, Anna keskipiste ); printf( Anna säde : ); scanf( %f, &c->r); } Huomautus. Sääntönä on, että ympyrän käyttöfunktioiden toteutuksissa, käytetään keskipisteen käsittelyyn pisteen käyttöfunktioita. Olisi väärin lukea keskipiste näin scanf( %f%f, &c->cp.x, &c->cp.y); Jos keskipisteen (alakomponentin) toteutustapa muuttuisi, niin pitäisi muuttaa myös ympyrän (pääkomponentin) toteutusta. Ylemmässä oikein tehdyssä tapauksessa ympyrän funktioita ei tarvitse muuttaa vaikka pisteen toteutus muuttuu, kunhan interface säilyy. 9
Ympyrän hierarkiamalli Ei sallittu Interface Ympyrä Interface Keskipiste Interface Säde x y 10
Miten saadaan ympyrän header ja musta laatikko Pisteen tapauksessa opimme, että pistekomponenttia käytetään otsikkotiedoston point.h ja mustan laatikon point.obj avulla. Kuinka saadaan vastaavat circle.h ja musta laatikko circle. Sitä tarkastellaan seuraavaksi. Edellytyksenä on, että pistettä voidaan käyttää sellaisenaan (siis header-tiedoston ja linkattavan mustan laatikon avulla) erikseen ja myös ympyrän toteutuksessa. Lisäksi sovellusohjelmoijan tulee voida käyttää ympyrää ympyränä ilman edes tietoa pisteestä tai myös yhdessä pisteen kanssa. Näiden vaatimusten täyttämiseen tarvitaan ehdollista kääntämistä ja kirjaston luontia. 11
Ehdollinen kääntäminen 1 Application programmers view: Case 1 (Application programmer needs only circles) #include "circle.h" void main (void) { Tcircle c; read_circle(&c);... } file circle.obj (or circle.lib) is linked Case 2 (Application programmer needs circles and points) #include "circle.h" #include "point.h" void main (void) { Tcircle c; Tpoint p; read_circle(&c);... } files circle.obj (or circle.lib) and point.obj are linked 12
Ehdollinen kääntäminen 2 A component programmer's view: The contents of file point.h : #ifndef _POINT interface of point //type and prototypes #define _POINT #endif The contents of circle.h is as follows: #ifndef _CIRCLE //#ifndef _POINT #include "point.h" //#endif typedef struct { Tpoint kp; float r; } Tcircle; void read_circle(tcircle *c);... #define _CIRCLE #endif // do not use but study what would be the effect //do not use 13
Miten tehdään musta laatikko circle.lib Visual Studio 2010 Solutions Testausprojekti (Tyyppinä 32 bit Console Application) testi.c circle.lib Ympyräprojekti (Tyyppinä library (static library).) circle.c point.obj Unix / Linux Testausprojekti gcc o testi.exe testi.c circle.a Ympyräprojekti gcc c circle.c o circle.o ar crv circle.a circle.o point.o (tulos on circle.a) Dev C++ Graafisessa ympäristössä libin tekeminen näyttää vaativan sourcet kaikista osista, eli ar ohjelmaa ei pystytä ohjaamaan IDEstä. Tällöin lib voidaan koota objekteista komentoriviltä käyttämällä suoraan ar ohjelmaa, kuten yllä on sanottu tapauksesta Unix/Linux. 14