Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3....

47
46 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka ovat yksinkertaisia ja lyhyitä. Modulaarisuudella pyritään parantamaan ohjelman ymmärrettävyyttä, testattavuutta sekä ylläpidettävyyttä. Funktio ryhmittää ohjelmalauseet yhdeksi ohjelmayksiköksi. Funktio suorittaa jonkin tarkasti rajatun tehtävän.

Transcript of Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3....

Page 1: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

46

3. Funktiot

Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka ovat yksinkertaisia ja lyhyitä. Modulaarisuudella pyritään parantamaan ohjelman ymmärrettävyyttä, testattavuutta sekä ylläpidettävyyttä. Funktio ryhmittää ohjelmalauseet yhdeksi ohjelmayksiköksi. Funktio suorittaa jonkin tarkasti rajatun tehtävän.

Page 2: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

47

Kaksi tasoa: • Valmiit kirjastofunktiot, esim. printf() ja scanf() • Ohjelmoijan itsensä kirjoittamat funktiot. Funktiot aktivoidaan suorittamalla funktion kutsu, joka on tavallinen C-kielen suoritettava lause: fnimi(); Funktion kutsu aloittaa funktion fnimi() ohjelmalauseiden suorituksen Kun funktion sisältämät lauseet on suoritettu, palataan takaisin siihen ohjelmaan, josta funktiota kutsutaan ja suoritetaan funktion kutsua seuraava lause.

Page 3: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

48

lause1; lause2; flause1; fnimi(); flause2; lause4; flause3; Funktion kutsussa sulkeet ovat pakolliset, niiden avulla kääntäjä osaa päätellä että kyseessä on funktio, eikä tavallinen muuttuja.

Page 4: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

49

Funktio täytyy määritellä ennenkuin sitä voidaan kutsua. Yleinen muoto yksinkertaistettuna on: funktion otsikko{ paikallisten muuttujien määrittelyt; suoritettavat lauseet; return arvo; } Funktio määritellään otsikkorivin ja lauselohkon avulla ( { ja }-merkkien välissä olevat lauseet). Otsikkorivillä ilmoitetaan funktion tyyppi, nimi ja parametrit. • Funktion tyyppi ilmoittaa funktion palauttaman arvon tyypin, jos funktio ei

palauta mitään niin tyyppinä on void.

Page 5: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

50

• Tyyppimäärite void esittää näennäistä tyyppiä, johon ei kuulu mitään arvoja. • Parametrit ilmoitetaan sulkujen sisällä. • Parametrejä voi olla yksi tai useampi, jokaisesta ilmoitetaan erikseen tyyppi

ja nimi. • Jos parametrejä ei ole käytetään tyyppinä void.

Page 6: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

51

• Funktion paikalliset muuttujat ovat käytettävissä vain funktion sisällä ja vain funktion suorituksen ajan.

• Suoritettavat lauseet käyttäytyvät kuten main()-funktiossakin. Funktiot on esiteltävä, jos funktioiden määrittelyt sijaitsevat main()-ohjelman perässä tai jossakin toisessa tiedostossa. Funktion esittelyä kutsutaan myös funktion prototyypiksi. Funktion prototyyppi kirjoitetaan ohjelmatiedoston alkuun esikääntäjän direktiivien jälkeen ennen main()-funktiota. Funktion esittelyssä käytetään funktion otsikko-osaa, jonka perään kirjoitetaan puolipiste.

Page 7: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

52

Esittelyjen avulla kääntäjä tutkii vastaavatko funktioiden kutsut ja määrittelyt toisiaan. • parametrien määrä, • järjestys ja • tyypit Esimerkkifunktio, joka "simuloi" kissaa: /* kissasimulaattori */ void naukaise( void ) { printf("Miau\n"); } Funktiota kutsuttaisiin. naukaise();

Page 8: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

53

Esimerkkiohjelma, jossa käytetään hyväksi kissa-funktiota. /* kissasimulaattori */ #include <stdio.h> void naukaise(void); /* funktion protyyppi, eli esittely */ int main(void) { /* kissa naukaisee */ naukaise(); return(0); } /* main loppuu tähän */ /* funktion naukaise määrittely eli toteutus */ void naukaise(void) { printf("Miau\n"); }

Page 9: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

54

Funktion parametrit Parametrien avulla funktiolle välitetään tietoa sen ulkopuolelta ja parametrejä käytetään funktiossa kuten paikallisia muuttujia. Parametrit eroavat paikallisista muuttujista siinä, että niille annetaan alkuarvo funktion ulkopuolelta eli funktion kutsussa. Kuten paikalliset muuttujat eivät parametritkään ole käytettävissä funktion ulkopuolella (ne eivät "näy" funktion ulkopuolelle). Eri funktioissa voi olla saman nimisiä muuttujia ja parametrejä, mutta ne ovat toisistaan täysin riippumattomia.

Page 10: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

55

Funktion otsikkossa (sekä esittelyssä että määrittelyssä) esiteltäviä parametrejä kutsutaan muodollisiksi parametreiksi. Funktion kutsussa annetut parametrit ovat todellisia parametrejä. Funktiota kutsuttaessa kopioidaan todellisen parametrien arvot funktion määrittelyssä vastaavassa kohdassa sijaitsevien muodollisten parametrien arvoiksi. Todellisten ja muodollisten parametrien tyyppien täytyy vastata toisiaan (joissakin tilanteissa C:ssä tehdään ns. automaattisia tyypin-muunnoksia ). Todellisten ja muodollisten parametrien nimien ei tarvitse olla samoja. Todellisena parametrina voi olla muuttujan tunnus, vakio, lauseke tai funktionkutsu.

Page 11: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

56

Arvon palauttavat funktiot

Funktiosta palataan takaisin kutsuvaan ohjelmaan: • funktion viimeisen lauseen suorittamisen jälkeen ja/tai • return-lauseella Jos funktion on palautettava arvo käytetään return-lausetta, jonka perään kirjoitetaan palautettava arvo. Palautettavan arvon tyypin on oltava funktion otsikossa esiteltyä tyyppiä. Funktiossa voidaan käyttää tyhjää return-lausetta, jos funktio ei palauta mitään ( funktion tyyppi on tällöin void ).

Page 12: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

57

Yleensä funktiossa on vain yksi return-lause, mutta mikään ei estä käyttämästä useampaakin (joista vain yksi suoritetaan!). Usean return-lauseen käyttö ei ole suositeltava tapa, koska se saattaa vaikeuttaa ohjelman lukemista ja ylläpitoa.

Page 13: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

58

Esimerkki: /* Funktio laskee kertoman n! esiehto: n on kokonaisluku ja suurempi tai yhtäsuuri kuin 0 */ int kertoma(int n){ int i, tulo = 1; for(i = 0; i <= n; i = i + 1){ tulo = tulo * i; } return ( tulo ); /* palauttaa luvun n kertoman */ }

Page 14: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

59

• funktion otsikossa ilmoitetaan palautettavan arvon tietotyyppi • funktio ei tulosta arvoaan, vaan palauttaa sen return-lauseella Funktion kommentti kertoo kaiken, mitä funktiosta pitää tietää, jotta funktiota voi käyttää. • mitä funktio tekee • mitä sille pitää antaa syöttietoina • mikä on syötettävien tietojen tyyppi • esiehto kertoo, mitä pitää olla totta ennenkuin funktiota voidaan kutsua Esimerkkiohjelma, joka käyttää edellä esiteltyä kertoma-funktiota.

Page 15: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

60

#include <stdio.h> /* funktion kertoma prototyyppi, eli esittely */ int kertoma ( int n ); /* Pääfunktio, joka kutsuu funktiota kertoma */ int main ( void ) { int num, tulos; printf ("Anna kokonaisluku väliltä 0 - 10 > "); scanf ("%d", &num ); /* tarkastetaan luvun arvo ennen funktion kutsumista */ if ( num >= 0 ) { tulos = kertoma ( num ); printf ("Luvun %d kertoma on %d\n", num, tulos ); } else { printf ("Luvun tulee olla positiivinen!"); } return ( 0 ); } /* main päättyy */

Page 16: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

61

/* Funktion kertoma määrittely eli toteutus Funktio laskee kertoman n! esiehto: n on kokonaisluku ja suurempi tai yhtäsuuri kuin 0 */ int kertoma ( int n ) { int i, tulo = 1; for ( i = 1; i <= n; i = i + 1 ) { tulo = tulo * i; } return ( tulo ); /* palauttaa luvun n kertoman */ }

Page 17: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

62

On myös mahdollista määritellä loogisia funktioita, joissa kokonaisluvut vastaavat loogisia arvoja tosi ja epätosi. /* Funktio, joka ilmoittaa onko argumenttina annettu kokonaisluku parillinen. Funktio palauttaa arvon true (1) jos luku on parillinen, muuten funktio palauttaa arvon false (0) */ bool parillinen(int luku){ bool vastaus; vastaus = ((num % 2) == 0); return(vastaus); }

Page 18: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

63

Käyttö ehtolausekkeena int x; printf(“Anna kokonaisluku”); scanf(“%d”, &x); if(parillinen(x)) printf("Luku on parillinen!"); Usean funktion kutsuminen lauseessa: tulos = kertoma(n) / (kertoma(r) * kertoma(n - r));

Page 19: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

64

Funktioiden tiedonvälitys Funktion ja sitä kutsuvan ohjelman osan välinen tiedonsiirto näkyy funktion otsikossa, funktiolle ei pitäisi välittää tietoa ns. globaalien muuttujien avulla. Funktiolle välitetään aina vain kopio todellisen parametrin arvosta. Jos funktion halutaan muuttavan kutsuvassa ohjelmassa olevan muuttujan arvoa, välitetään todellisena parametrina muuttujan osoite (oikeastaan kopio osoitteen arvosta). Kun parametrin arvo on muuttujan osoite käytetään nimeä osoiteparametri, muussa tapauksessa on kyseessä arvoparametri.

Page 20: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

65

Funktion ja sitä kutsuvan ohjelman väliseen tiedonsiirto on kaksi tapaa: • arvoparametri ja return-lause • osoiteparametri Lisäksi näiden eri variaatiot

Page 21: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

66

Funktiot ja osoiteparametrit Funktio voi palauttaa return-lauseella korkeintaan yhden arvon. Jos funktion on palautettava useita arvoja, käytetään osoite-parametreja välittämään tietoa ulos funktiosta. Esimerkki funktiosta, joka palauttaa parametrina annetun reaaliluvun etumerkin, kokonaisosan ja desimaaliosan.

Page 22: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

67

#include <stdio.h> #include <math.h> /* erota -funktion esittely */ void erota(double num, char *merkkio, int *kokoaiso, double *desio); int main(void){ double luku, desimaaliosa; char etumerkki; int kokonaisosa; printf(" Anna reaaliluku >"); scanf("%lf", &luku ); erota (luku, &etumerkki, &kokonaisosa, &desimaaliosa); printf("Luvun %.4lf osat\ etumerkki: %c\n", luku, etumerkki ); printf("kokonaisosa: %d\n", kokonaisosa); printf("desimaaliosa: %.4lf\n", desimaaliosa); return ( 0 ); } /* main */

Page 23: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

68

/* erota-funktio saa erottaa in-parametrina saamansa reaaliluvun osiinsa. num: in, erotettava reaaliluku *merkkio: out, etumerkki *kokonaiso: out, kokonaisosa *desio: out, desimaaliosa */ void erota(double num, char *merkkio,int *kokonaiso, double *desio ){ double n; /* paikallinen muuttuja */ if ( num < 0 ) *merkkio = '-'; else if ( num == 0 ) *merkkio = ' ' ; else *merkkio = '+'; n = fabs(num); /* luvun n itseisarvo */ *kokonaiso = floor(n); /* kokonaisosa */ *desio = n - *kokonaiso; /* desimaaliosa */ }/* erota */

Page 24: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

69

main-funktion parametrit

main()-funktiolle voidaan välittää tietoja kutsuttaessa ns. komentori-viparametrien avulla. Komentoriviparametrit kirjoitetaan ohjelman nimen perään, kun ohjelma käynnistetään komentoriviltä. Käyttöjärjestelmä välittää mitkä tahansa komentoriviparametrit ladattavalle ohjelmalle.

Page 25: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

70

Ohjelma, joka tulostaa saamansa komentoriviparametrit: int main (int argc, char * argv[]){ int laskuri; printf("Parametrien lukumäärä: %d\n", argc ); for ( laskuri = 0; laskuri < argc; laskuri++) { printf("Parametri %d on %s\n", laskuri, *(argv+laskuri) ); } return ( 0 ); }

Page 26: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

71

Ensimmäisen parametri argc kertoo kokonaislukuna annettujen parametrien lukumäärän. Toinen parametri argv[] on osoitin merkkijonotaulukkoon, jonne kaikki parametrit on talletettu syöttöjärjestyksessä. Ensimmäisen merkkijonotaulukon alkion sisältönä on aina suoritettavan ohjelman koko hakemistopolku.

Page 27: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

72

Talletusluokat (Storage classes) C-kielessä on erilaisia talletusluokkia (muistimääreitä), jotka vaikuttavat muuttujien ja funktioiden näkyvyyteen ja elinikään. 1. auto Funktioiden muodollisille parametreille ja paikallisille muuttujille varataan tilaa automaattisesti ja näiden muuttujien käyttämä tila vapautetaan automaattisesti, kun funktion suoritus päättyy.

Page 28: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

73

2. extern Funktioille voidaan joissakin tilanteissa välittää tietoa muuttujien avulla, jotka on määritelty kaikkien funktioiden ulkopuolella ns. globaalit muuttujat. Globaali muuttuja "näkyy" kaikissa funktioissa, jotka on määritelty globaalin muuttujan määrittelyn jälkeen. Globaaleille muuttujille varataan tilaa koko ohjelman suorituksen ajaksi. Globaalin muuttujan näkyminen voidaan peittää funktiossa määrittelemällä uusi samanniminen paikallinen muuttuja. Kaikki funktioiden nimet ovat tyyppiä extern, eli funktioiden nimet nimet ovat globaaleja.

Page 29: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

74

Globaalien muuttujien käyttö ei ole vaaratonta, esimerkiksi ohjelmoijalla on tarkoitus käyttää paikallista muuttujaa, jolla on sama nimi kuin globaalilla muuttujalla. Kaikki paikalliseen muuttujaan kohdistuvat toimenpiteet suoritetaan globaaliin muuttujaan, josta seuraa melko varmasti virhetilanne, joka voi olla vaikea havaita.

Page 30: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

75

Esimerkkiohjelma: #include <stdio.h> int a = 1, b = 2, c = 3; /* globaaleja muuttujia */ int summa(void); /* funktion prototyyppi */ int main ( void ) { printf("%3d\n", summa()); printf("%3d%3d%3d\n", a, b, c ); return (0 ); } /* funktion summa määrittely */ int summa ( void ) { int b, c; /*paikalliset b ja c,globaalit b ja c peittyvät*/ a = b = c = 4; return ( a + b + c ); }

Page 31: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

76

Globaalin muuttujan määrittelyssä ei käytetä sanaa extern, muuttujaa esiteltäessä. Sanalla extern kerrotaan kääntäjälle "etsi esiteltävän muuttujan määrittely muualta joko tästä tai toisesta tiedostosta". Esimerkiksi jos edellinen ohjelma kirjoitettaisiin kahteen eri tiedostoon.

Page 32: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

77

tiedosto file1.c: #include <stdio.h> int a = 1, b = 2, c = 3; /* globaaleja muuttujia */ int summa ( void ); /* funktion prototyyppi */ int main ( void ) { printf("%3d\n", summa( ) ); printf("%3d%3d%3d\n", a, b, c ); return (0 ); }

Page 33: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

78

tiedosto file2.c: /* funktion summa määrittely */ int summa ( void ) { extern int a; /* etsi a:n määrittely muualta */ int b, c; /*paikalliset c ja b, globaalit b ja c peittyvät*/ a = b = c = 4; return ( a + b + c ); }

Page 34: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

79

3. register register-muistimääreellä kerrotaan kääntäjälle, että jos vain on mahdollista niin muuttujalle varataan tila koneen keskusyksikön rekistereistä, eikä keskusmuistista. Tarkoituksena on tehostaa ohjelman suoritusta. Määre on vain ehdotus kääntäjälle, jos rekistereitä ei ole joutilaana, varataan muuttujalle tilaa normaalisti keskusmuistista.

Page 35: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

80

Tyypillisiä ehdokkaita ovat silmukkalaskurit ja funktioiden parametrit, esimerkiksi: { register int i; for(i = 0; i < LIMIT; i++){ .... } } Lohkosta poistuminen vapauttaa muuttujan i. Jos muuttujan määrittelyssä jätetään tyyppi ilmoittamatta, mutta talletusluokka ilmoitetaan, on tyyppi oletusarvoisesti int.

Page 36: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

81

4. static static-määrettä käytetään kahdessa eri tarkoituksessa. Paikalliset muuttujat säilyttävät arvonsa kun samaan lohkoon tullaan uudestaan, toisin kuin automaattisten muuttujien kohdalla. Esimerkiksi funktio, joka toimii eri tavalla riippuen montako kertaa sitä on kutsuttu. void teeJotakin ( void ) { static int lkm = 0; lkm++; if ( lkm % 2 == 0) ... /* tee jotakin */ else ... /* tee jotakin muuta */

Page 37: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

82

lauseessa static int lkm = 0; alustetaan muuttujalle lkm arvo 0 vain funktion teeJotakin ensimmäisellä suorituskerralla. static -määreen käyttö globaalien nimien yhteydessä antaa mahdollisuuden rajoittaa muuttujien ja funktioiden "näkyvyyttä". Näkyvyys rajataan vain sen tiedoston loppuun, jossa muuttuja tai funktio on määritelty ts. muuttujat eivät näy funktioissa, jotka on esitelty ennen muuttujan määrittelyä eikä funktioissa, jotka on määritelty eri tiedostoissa.

Page 38: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

83

Esimerkiksi: void funktioYksi(void) { ... /* muuttuja v ei ole käytettävissä */ } static int v; /* static external v */ void funktioKaksi ( void ) { ... /* v:tä voidaan käyttää täällä */ }

Page 39: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

84

Myöskin funktion näkyminen voidaan rajoittaa esim: static int funktioG(void); /* prototyyppi */ void funktioF(void){ /* funktion määrittely */ ... /*funktioG() "näkyy" täällä, mutta ei muissa tiedostoissa*/ } static int funktioG(void){ ... }

Page 40: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

85

C-kielessä globaalit ja staattiset muuttujat alustetaan automaattisesti nollaksi ellei ohjelmoija anna niille alkuarvoja. Automaattisia ja rekisterimuuttujia ei alusteta automaattisesti.

Page 41: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

86

Funktiokirjastot C-kielessä on valmiiksi määriteltyä funktioita, jotka on koottu funktiokirjastoihin, jotka on jaettu useisiin pienempiin ryhmiin. Funktiokirjastot otetaan käyttöön #include-komennolla kirjoittamalla komennon perään tarvittavan otsikkotiedoston nimi kulmasulkeissa. #include <stdio.h> Otsikkotiedosto sisältää funktioiden määrittelyt. Kulmasulkeet ilmoittavat kääntäjälle, että sisältö sijaitsee standardikirjasto-hakemistossa. C:n standardikirjasto koostuu 15 otsikkotiedostosta.

Page 42: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

87

Otsikkotiedosto Kuvaus assert.h ohjelmien diagnostiikkatoimintoja ctype.h merkkien testausfunktioita locale.h maa- ja kieli-informaatiota tarjoavia funktioita math.h matemaattiset funktiot setjmp.h mahdollistaa ohjelman kulun muuttamisen

funktioilla signal.h poikkeustilanteiden käsittelyfunktiot stdarg.h muuttuja-argumenttien käsittelymakroja stdbool.h loogisen tietotyypin määrittelyt stddef.h tietotyyppien ja makrojen määrittelyitä stdio.h syöttö- ja tulostusfunktioita stdlib.h erilaisia hyötyfunktioita string.h merkkijonojen käsittelyfunktiot time.h päivänmäärä- ja aikafunktioita

Page 43: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

88

Matemaattiset funktiot. Funktio Kuvaus abs () kokonaislukumuuttujan itseisarvo fabs() reaalilukumuuttujan itseisarvo sin() luvun sini cos() luvun kosini tan() luvun tangentti asin() luvun arcussini acos() ... atan() ... log() luonnollinen logaritmi log10() 10-kantainen logaritmi exp() eksponenttifunktio sqrt() neliöjuuri pow() luvun korotus potenssiin

Page 44: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

89

Aika- ja päivänmääräfunktiot Otsikkotiedostossa time.h määritellään funktioita, joilla käsitellään aikaa ja päivänmäärää. Funktioiden avulla voidaan käyttöjärjestelmältä kysyä aika ja päivänmäärä, sekä muuntaa aikamuotoja. Useissa ympäristöissä päivänmäärä ja aika ilmaistaan sekunteina, joka on kulunut päivänmäärästä 1.1.1970. Funktio kuvaus stime() asettaa ajan ja päivänmäärän time() palauttaa ajan aikana (GMT) asctime() muuntaa ajan muodosta toiseen clock() palauttaa kuluneen prosessoriajan

Page 45: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

90

Tiedostossa stdlib.h on useita hyötyfunktioita, joista alla muutamia yleisimmin käytettyjä Funktio kuvaus rand() Palauttaa satunnaisluvun srand() Alustaa satunnaislukugeneraattorin exit() ohjelman keskeytys (yleensä

virhetilanteessa ) abort() ohjelman epänormaali keskeytys mallaoc() muistin allokointi realloc() vapauttaa muistia free() palauttaa allokoidun muistin järjestelmälle system() suorittaa käyttöjärjestelmätoiminnon qsort() lajittelee taulukon, quicksort-algoritmia

käyttäen

Page 46: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

91

Merkkienkäsittelyfunktiot Funktio kuvaus isalpha() onko merkki aakkonen iscntrl() onko merkki ohjausmerkki ispunct() onko merkki välimerkki isspace() onko merkki välilyönti isupper() onko merkki iso kirjain islower() onko merkki pieni kirjain tolower() muuttaa kirjaimen pieneksi kirjaimeksi toupper() muuttaa merkin isoksi kirjaimeksi

Page 47: Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin ...janneku/T080104/SAU14SNS/C/C_OSA3.pdf · 3. Funktiot Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka

92

Yhteenveto: • return-lause päättää funktion suorituksen ja palauttaa kontrollin kutsuvalle

ympäristölle. • Jos return-lause sisältää lausekkeen, lasketaan lausekkeen arvo ja sen arvo

palautetaan kutsujalle. • Funktion prototyyppi kertoo kääntäjälle funktiolle välitettävien parametrien

tyypin ja lukumäärän sekä funktion palauttaman arvon tyypin. Jos funktiolle ei välitetä parametreja käytetään sanaa void. Jos funktio ei palauta mitään käytetään sanaa void.

• Funktiolle välitetään parametrina aina kopio todellisen parametrin arvosta,

joka voi olla joko muutujan sisältö tai sen osoite. Välitettävän tiedon tyypin ja järjestyksen täytyy vastata funktion prototyypissä ja määrittelyssä ilmoitettua tyyppiä ja järjestystä.