Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

3.10.2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Funktio-osoittimet Funktio-osoittimen ja taulukko-osoittimen vertailu Funktio-osoittimen käyttötapoja.

Samankaltaiset esitykset


Esitys aiheesta: "3.10.2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Funktio-osoittimet Funktio-osoittimen ja taulukko-osoittimen vertailu Funktio-osoittimen käyttötapoja."— Esityksen transkriptio:

1 3.10.2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Funktio-osoittimet Funktio-osoittimen ja taulukko-osoittimen vertailu Funktio-osoittimen käyttötapoja funktio taulukon alkiona funktio funktion parametrina funktio palauttaa funktion Kuinka qsort käyttää funktioparametria Iteraattorit

2 3.10.2012 © Hannu Laine 2 Funktiot ja niiden osoittimet  Funktion nimi on vakio-osoitin, jolla on oma (kohde)tyyppinsä  Voidaan määritellä osoitinmuuttuja, jonka kohdetyyppi on funktio.  Funktion osoite (nimi) voidaan tallentaa (sijoittaa) tällaiseen muuttujaan.  Funktiota voidaan kutsua myös tällaisen muuttujan kautta (kunhan sinne on sijoitettu kutsuttavan funktion osoite).  Esimerkki int f1(int); // f1 on funktio eli f1 on vakio-osoitin int *f2(int); // f2 on funktio eli f2 on vakio-osoitin int (*f3)(int); // f3 on osoitinmuuttuja, jonka kohdetyyppi on // funktio int *(*f4)(int); // f4 on osoitinmuuttuja, jonka kohdetyyppi on funktio  Nyt voidaan tehdä sijoitukset f3 = f1; ja f4 = f2;  Funktiota f1 voidaan kutsua normaalisti esimerkiksi tavalla f1(2);  Sitä voidaan kutsua myös muuttujan f3 kautta näin f3(2); (Kieliopillisesti olisi myös oikein sanoa (*f3)(2) )

3 3.10.2012 © Hannu Laine 3 Funktio- ja taulukko-osoittimen vertailu Funktio  Funktion nimi on vakio-osoitin, jolla on oma (kohde)tyyppinsä  Osoitin osoittaa funktion ensimmäistä suoritettavaa käskyä  Voidaan määritellä osoitinmuuttuja, jonka kohdetyyppi on funktio  Funktiota kutsutaan ts. käskyjä aletaan suorittaa liittämällä osoitteeseen kutsusulkeet () sisältäen parametrit.  Funktiota voidaan kutsua (asettaa kutsusulut) osoitinmuuttujan kautta. Taulukko  Taulukon nimi on vakio-osoitin, jolla on oma (kohde)tyyppinsä  Osoitin osoittaa taulukon ensimmäistä alkiota  Voidaan määritellä osoitinmuuttuja, jonka kohdetyyppi on taulukon alkio.  Taulukosta valitaan alkioita liittämällä osoitteeseen indeksointisulkeet sisältäen indeksin.  Taulukkoa voidaan käsitellä (valita alkioita, asettaa indeksointisulut) osoitinmuuttujan kautta.

4 3.10.2012 © Hannu Laine 4 Funktio-osoittimen käyttötapoja  Siitä, että funktiota voi edustaa muuttuja (osoitinmuuttuja) seuraa, että funktio voi olla taulukon alkiona funktio voi olla funktion parametrina funktio voi palauttaa funktion funktio voi olla tietueen kenttänä jne

5 3.10.2012 © Hannu Laine 5 Oma switch-rakenne funktiotaulukolla //Funktioiden prototyypit int f1(void); int f2(void); int f3(void); //Vaihtoehto: typedef int (*Tf)(void);  void main(void) { int ( *ft [3] ) (void) = { f1, f2, f3 } ;  //Vaihtoehto: Tf ft [3] = { f1, f2, f3 } ;  int valinta, funktionTulos; scanf(”%d”, &valinta); // Väliltä 0 - 2 funktionTulos = ft[valinta](); } Ohjelma suorittaa funktion f1, f2 tai f3 sen mukaan, onko syötetty 0, 1 tai 2. Huomautus. Kolmiolla merkitty rivi voidaan korvata neliöillä merkityillä riveillä. //Funktioiden toteutukset int f1(void) {return 1; } int f2(void) {return 2; } int f3(void) {return 3; }

6 3.10.2012 © Hannu Laine 6 Funktiotaulukkoa edustava osoitin Edellisen sivun funktio-osoittimien taulukon määrittely int (*ft1[3])(void); Varaa muistista 3 osoitinta. Tässäkin, kuten kaikissa taulukoissa, taulukon nimi ft1 on taulukon ensimmäisen alkion vakio-osoitin. Osoitinmuuttuja, joka edustaa funktio-osoittimien taulukkoa on silloin: int (**ft2) (void); Nyt voi tehdä sijoituksen ft2 = ft1; jonka jälkeen esim: ft1[1](); ft2[1](); Jos olisi funktio kayta_funktiotaulukkoa, joka ottaa parametriksi yllä olevan funktiotaulukon, sen prototyyppi olisi esimerkiksi void kayta_funktiotaulukkoa (int (**par) (void)); Tätä funktiota voitaisiin kutsua muodossa kayta_funktiotaulukkoa (ft1);

7 3.10.2012 © Hannu Laine 7 Funktio funktion parametrina (qsort) 1 Esimerkkinä funktio qsort void qsort(void *base, size_t n, size_t size, int (*fcmp) (const void*, const void *)); typedef struct { int age; char name[30]; } Tperson; int compareNames(const void *p1, const void *p2); int compareAges(const void *p1, const void *p2); int main(void) { Tperson array[100]; //Muodostetaan taulukko qsort(array, 100, sizeof(Tperson), compareNames); //Nyt taulukko on järjestyksessä nimen mukaan qsort(array, 100, sizeof(Tperson), compareAges); //Nyt taulukko on järjestyksessä iän mukaan } Funktion qsort prototyyppi Tietueen Tperson määrittely Vertailufunktioi- den prototyypit Sovellus, jossa taulukko järjestetään

8 3.10.2012 © Hannu Laine 8 Funktio funktion parametrina (qsort) 2 //Vertailufunktioiden toteutukset: int compareNames(const void *p1, const void *p2) { return strcmp(((Tperson*) p1)->name, ((Tperson*) p2)->name); } int compareAges(const void *p1, const void *p2) { if (((Tperson*) p1)->age age) return -1; if (((Tperson*) p1)->age == ((Tperson*) p2)->age) return 0; return 1; } Huomautus. Vertailufunktiot tietueelle Tperson voidaan kirjoittaa myös niiden ”luonnollisessa” muodossa seuraavasti: int compareNames(const Tperson *p1, const Tperson *p2) { return strcmp(p1->name, p2->name); } Silloin tarvitaan tyyppimuunnos funktion qsort kutsussa seuraavasti: qsort(array, 5, sizeof(Tperson), (int (*)(const void*, const void*)) compareNames);

9 3.10.2012 © Hannu Laine 9 Kuinka qsort käyttää funktioparametria Qsort käyttää parametrina saamaansa funktiota taulukon alkioiden vertailuun. Se kutsuu järjestämisprosessissa vertailufunktiota useita kertoja ja siirtää alkioita taulukossa vertailutulosten mukaisesti oikeaan järjestykseen. Tutustumme tähän periaatteeseen yksinkertaisen lajittelumenetelmän avulla. Tarkastelemme esimerkkiä, jossa selection sort menetelmällä on tehty geneerinen järjestämisfunktio sort_selection. Tämän esimerkkifunktion parametrilista on täsmälleen sama kuin qsort- funktion, jolloin nähdään kuinka asiat tapahtuvat järjestämisfunktion ”sisällä”. Esimerkkiohjelma löytyy verkosta.

10 3.10.2012 © Hannu Laine 10 Funktio palauttaa funktion (signal) Unix/Linux-käyttöjärjestelmien API-rajapinnalla on funktio signal, jolla asetetaan signaalinkäsittelijäfunktio. Funktio signal ottaa signaalinkäsittelyfunktion parametrina ja palauttaa ennen asetusta käytössä olleen signaalinkäsittelyfunktion. Tämän funktion prototyyppi on void (*signal ( int signo, void(*func)(int)))(int); Tätä voitaisiin käyttää seuraavasti: void my_handler(int signo); int main(void) { void (*old_handler)(int); … old_handler = signal(SIGALRM, my_handler); …. signal(SIGALRM, old_handler); } void my_handler(int signo) { return; } Asetetaan uusi signaalinkäsittelijä- funktio. Palautetaan alkuperäinen

11 3.10.2012 © Hannu Laine 11 Sisäinen iteraattori 1 Iteraattori voi olla sisäinen tai ulkoinen. Sisäinen iteraattori tarkoittaa, että säiliö itse osaa läpikäydä alkionsa. Säiliöllä on silloin operaatiofunktio ForAll, ForEach tms. Tällaisen funktion prototyyppi C:ssä voisi olla on muotoa void ForAll(Tcontainer *cont, void (*f)(Titem *item)); missä f on parametrina annettava funktio, jonka käyttäjä voi vapaasti kirjoittaa ja jossa kuvataan, mitä alkioille tehdään. Tarkastellaan tarkemmin esimerkkinä listan sisäistä iteraattoria. Sitä käytetään esimerkissä ensin listan alkioiden tulostamiseen ja sitten siten, että alkioihin lisätään 1. (Katso verkossa oleva esimerkkiohjelma sisiter.c)

12 3.10.2012 © Hannu Laine 12 Sisäinen iteraattori 2 Jos alkiota käsittelevä funktio halutaan yleisemmäksi siten, että sille voidaan välittää parametreja, sen muoto on esimerkiksi void (*f)(Titem *item, void *args); Funktion ForAll prototyyppi on silloin: void ForAll(Tcontainer *cont, void (*f)(Titem *, void *), void *args); Tällöin sisäisen iteraattorin kutsu voisi olla esimerkiksi muotoa int lisays = 3; ForAll(&stack, lisaaluku, &lisays); Parametrin lisays oikea tyypitys tehdään itse funktiossa. Kutsussa olevan funktion lisaaluku toteutus olisi silloin void lisaaluku(Titem *item, void *args) { *item = *item + *(int*)args; } Funktion ForAll toteutus tässä tapauksessa olisi ….


Lataa ppt "3.10.2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Funktio-osoittimet Funktio-osoittimen ja taulukko-osoittimen vertailu Funktio-osoittimen käyttötapoja."

Samankaltaiset esitykset


Iklan oleh Google