Funktsioonid osa 1

Märksõnad: funktsioonid C-keeles (sissejuhatus), parameetrite tüübid, harjutus

Definitsioon:

Funktsioon e. function, meetod e. method - lähtekoodi osa, mis täidab kindlat ülesannet. Funktsioon on korduvkasutatav e. väljakutsutav erinevatest programmi osadest, vähendades seega programmi loomise ajakulu, haldamise vaeva ja koodi pikkust.
(allikas: http://et.wikipedia.org/)

C-keele põhifunktsiooniga oleme juba kokku puutunud - see on funktsioon main. Lisaks olema kasutanud muid C-keele funktsioone (sisestus/väljastus, teisendamine jne.)

Funktsiooni deklareerimine

Funktsiooni deklaratsioon on samal ajal ka funktsiooni prototüübiks. Funktsioon deklareeritakse järgmiselt:

andmetüüp funktsiooni_nimi (parameeter1, parameeter2, ...)


Funktsiooni definitsioon ehk kirjeldus on järgmise struktuuriga:

andmetüüp funktsiooni_nimi (parameeter1, parameeter2, ...)
{
lokaalsete muutujate deklareerimine;
funktsiooni keha;
return funktsiooniväärtus;
}



andmetüüp
Funktsiooni poolt tagastatava väärtuse tüüp. Näiteks kui funktsioon tagastab täisarvu, on tüübiks int, kui reaalarvu, siis double jne.

funktsiooni_nimi
Nimi, mille abil funktsiooni poole pöördutakse.

parameetrid
Parameetreid võib olla täpselt niipalju kui vaja - nende arv ja tüüp määratakse peale funktsiooni nime sulgudes. Iga parameeter koosneb tüübist ja nimest (näiteks int x, double y jne), erinevad parameetrid eraldatakse komadega. Funktsiooni sees käitvad need parameetrid samamoodi nagu suvaline muutuja. Parameetrid võimaldavad edastatada väärtusi funktsioonile selle poole pöördumisel.

lokaalsete muutujate deklareerimine
Funktsiooni tööks võivad olla vajalikud lisamuutujad, mida kasutatakse vaid selle funktsiooni piires. Sellisel juhul on vajalik lokaalsete muutujate deklareerimine, mis käib sarnaselt enne tutvustatud muutujate deklareerimisega. Meeles tuleb pidada, et selliste muutujate väärtused on kehtivad vaid funktsiooni sees.

funktsiooni keha
Ehk siis rida lauseid mis kirjeldavad täpselt, mida see funktsioon tegema peab (funktsiooni algoritm).

return funktsiooniväärtus
Milline väärtus saab funktsiooni väärtuseks selle poole pöördumisel.


Vaatame järgmist näidet:

#include <stdio.h>

//funktsiooni kirjeldus
int liidaArvud(int a, int b)
{
int s;
s=a+b;
return (s);
}

//funktsiooni main
int main (void)
{
int summa;

//pöördumine eelpool kirjeldatud funktsiooni poole 

summa = liidaArvud (5,3);
printf("\nKui liita 5 ja 3, on tulemuseks %d",summa);

getchar();
return 0;
}


Sellise programmi käivitamisel väljastatakse ekraanile:

Kui liita 5 ja 3 on tulemuseks 8



Funktsioonis main deklareeritakse üks täisarvuline (int) muutuja nimega summa. kohe peale seda pöördutakse funktsiooni liidaArvud poole (seega katkestab main natukeseks ajaks oma töö ning tööle hakkab liidaArvud) - funktsioonile etteantavad väärtused 5 ja 3 vastavad funktsiooni parameetritele int a ja int b:



Pöördumisel funktsiooni liidaArvud poole edastatakse sellele väärtused 5 ja 3 ning need kopeeritakse funktsioonisiseste lokaalsete muutujate int a ja int b väärtusteks. Funktsioonis deklareeritakse ka üks muutuja - int s ning tehte s = a + b; kaudu antakse muutujale s väärtuseks a ja b summa ehk siis s saab väärtuseks 8 (kuna edastati väärtused 5 ja 3)

Lause

return (s);

lõpetab funktsiooni liidaArvud töö ning edastab saadud väärtuse funktsioonile main, peale mida jätkab main tööd lausest mis järgneb funktsiooni liidaArvud poole pöördumisele.



Nagu definitsioonis öeldud, saab funktsioonide poole pöörduda mitu korda, kusjuures iga kord edastatakse erinevaid väärtusi.

Näide:

Uuri toodud näidet ja proovi aru saada mida programmis tehakse. Proovi toodud näide ka käivitada.



#include <stdio.h>

int liidaArvud(int a, int b)
{
  int s;
  s=a+b;
  return (s);
}

int main (void)
{
  //muutujate deklareerimine
  int esimeneSumma, teineSumma, kolmasSumma;
  int esimeneLiidetav, teineLiidetav, kolmasLiidetav, neljasLiidetav;
 
  //pöördume funktsiooni poole esimest korda
  esimeneSumma = liidaArvud (5,3);
  printf("\nKui liita 5 ja 3, on tulemuseks %d",esimeneSumma);

  esimeneLiidetav=7;
  teineLiidetav=6;
  //pöördume funktsiooni poole teist korda
  teineSumma=
liidaArvud(esimeneLiidetav,teineLiidetav);
  printf("\nKui liita %d ja %d, on tulemuseks %d",esimeneLiidetav, teineLiidetav, teineSumma); 

  printf("\nSisesta yks arv: ");
  scanf("%d",&kolmasLiidetav);
  printf("\nSisesta teine arv: ");
  scanf("%d", &neljasLiidetav);
  //pöördume funktsiooni poole kolmandat korda
  kolmasSumma=
liidaArvud(kolmasLiidetav,neljasLiidetav);
  printf("\nKui liita %d ja %d, on tulemuseks %d\n",kolmasLiidetav, neljasLiidetav, kolmasSumma); 
 
  getchar();
  return 0;
}




Eelpool vaatasime funktsiooni kis tagastab mingi väärtuse. Võivad aga olla ka funktsioonid mis mitte mingit väärtust ei tagasta: näiteks funktsioon, mis lihtsalt väljastab midagi. Toome näiteks funktsiooni, millel on kaks parameetrit - stringmuutuja ja täisarv ning funktsiooni ülesandeks on need väärtused lihtsalt ekraanile tuua:



void vanusEkraanile(char *n, int v)
{
    printf("\nTere %s, sa oled %d aastat vana\n", n, v);
}


Sellise funktsiooni poole pöördume lihtsalt:

vanusEkraanile(sinuNimi,sinuVanus);






Parameetrite tüübid jagunevad:
  • väärtusparameeter (by value)
    sellisel juhul tehakse parameetri väärtusest koopia ja edastatakse funktsioonile, nagu oli liitmise näites kus kasutasime funktsiooni liidaArvud; väärtusparameetri kasutamisel ei ole funktsioonil võimalik seda väärtust muuta - funktsioon saab vaid väärtust kasutada.

  • viidaparameeter (by reference)
    sellisel juhul edastatakse edastatakse parameetri aadress, nagu oli nime väljastamise näites eelpool; viidaparameetri kasutamisel on funktsioonil võimalus ka etteantud väärtust muuta, kuna ta edastatakse selle asukoht

Tasub meelde jätta:
  • Muutuja – väärtusparameetrina (juhul kui me ei soovi selle väärtust muuta)
  • massiiv (ka char[]) - viidaparameetrina



Vaatleme jälle näidet, kus milles programm küsib kasutaja nime ning sünniaasta ning arvutab tema vanuse. Väljastatakse nimi ja väljaarvutatud vanus.

Alltoodud programmi kompileerimine Terminalis:
gcc -o prog31 prog31.c

Kompileeritud programmi käivitamine Terminalis:
./prog31






Ava esimesel programeerimise tunnil loodud programm.
Kasutades seda ja eeltoodud näidet loo järgmine programm.
  • programm väljastab töö käigus järgmist (tavaline tekst on see, mida väljastab arvuti,
    rasvane tekst on see, mida sisestab kasutaja):


    Tere, mis on sinu nimi?
    Juku

    Liidame kaks arvu
    Sisesta esimene arv: 15
    Sisesta teine arv: 7
    Juku, arvude 15 ja 7 summa on 22

    Proovime jagada
    Sisesta jagatav: 15
    Sisesta jagaja: 7
    Kui jagame 15.00 arvuga 7.00, on tulemuseks 2.143

  • NB! loo järgmised funktsioonid:
    1. kahe täisarvu (int) liitmine, ning tulemuse tagastamine (return)
    2. Stringi (char[]) kolme täisarvu (int) väljastamine ekraanile
    3. Ühe reaalarvu jagamine teisega (double), tulemuse tagastamine (return)
    4. Stringi (char[]) ning kolme reaalarvu (double) väljastamine ekraanile

  • Järgmiseks proovi luua funktsioon (näiteks nimega arvutaJaV2ljasta), mis kasutaks kahte enne loodud funktsiooni (vaata eelmises punktis a ja b), seega toimiks programm umbes järgmiselt:
    • main pöördub arvutaJaV2ljasta poole
    • arvutaJaV2ljasta pöördub järjest liitmise ja väljastamise (eelmise punkti a ja b) funktsioonide poole

  • Proovi sama punktide c ja d jaoks

Kasutatud materjal:

Koostas: Helena Kruus (MSc)
viimati muudetud: 19. oktoober 2010