Funktio on itsenäinen ohjelman osa, joka tekee jonkin halutun tehtävän,
se voi esimerkiksi
laskea jonkin laskutoimituksen. Seuraavassa esimerkissä
funktio laskee
kartion tilavuuden,
funktion alussa esitellään ne muuttujat, joita funktio
tarvitsee. Funktion täydellinen nimi koostuu kolmesta asiasta, paluuarvon
tyyppistä, funktion nimestä ja optiona parametreista.
Edellinen ohjelma laskee kartion tilavuuden ja tulostaa tiedot
ruudulle, muttei pysty välittämään tietoa muille funktioille. Muuttujat Sade, Korkeus ja Tilavuus
ovat tämän funktion
paikallisia
muuttujia.
Funktioihin sisältyvät ohjelmassa tarvittavat toiminnot. Funktioon
voidaan sen käynnistyessä viedä tietoa ja se voi päätyttyään palauttaa kutsujalleen
tietoa. Tieto viedään parametrien avulla ja palautetaan return-käskyn perässä olevalla
muuttujalla. Tietoa voidaan
palauttaa myös parametreissa.
KartionTilavuus(); //kutsutaan itse tehtyä funktiota nimeltään KartionTilavuus
getch();//jäädään
odottamaan, että käyttäjä painaa jotain nappulaa
Pääohjelmasta tai mistä tahansa funktiosta toinen funktio voidaan
kutsua sen nimellä + (parametrit, jos on).
Funktio esitellään ennen sen käyttöä. Funktion esittelyä sanotaan myös
funktion prototyypiksi. Esittely tapahtuu seuraavasti:
Funktion esittelyn tarkoituksena on kertoa kääntäjälle (kääntäjä
kääntää ohjelmoijan koodin koneen ymmärtämään muotoon) etukäteen
millaisia funktioita ohjelmassa on, lisäksi kerrotaan miten funktiota
voidaan kutsua, jotta kääntäjä voi tarkastaa, menikö kutsu oikein. Jos
kutsu oli virheellinen, antaa kääntäjä siitä virheilmoituksen.
Funktioiden esittelyt laitetaan ohjelman alkuun tai erillisiin
otsikkotiedostoihin. Kuten edellä nähdään funktioiden parametrien nimiä
ei välttämättä tarvita esittelyssä.
Funktion
paluuarvo
Funktio voi päätyttyään palauttaa kutsujalleen tietoa.
Tieto palautetaan return-käskyn perässä olevalla muuttujalla.
Funktiossa voi olla useita return lauseita sopivissa kohdissa. Funktion
nimen edessä oleva tyyppi määrää paluuarvon tyypin ja siksi return
lauseen perässä olevan muuttujan tyypin pitää olla sama.
#include <stdio.h>
#include <conio.h>
char KysyMerkki()//funktion tyyppi on nyt char ja funktio paluttaa nyt kutsujalle näppäimistöltä annetun merkin
{
char Merkki;
printf("anna jokin merkki: ");
Merkki= getch();//kysytään merkki näppäimistöltä
return getch();//palautetaan kysytty muuttuja funktiosta return lauseella KysyMerkki funktion kutsujalle
}
void TulostaMerkki(char Merkki) //funktion parametrina char tyyppinen muuttuja
{
printf("Antamasi merkki oli %c",Merkki );//tulostetaan annettu merkki %c:n osoittamaan kohtaan
}
int main()
{
char JokinMerkki;//esitellään muuttuja, nyt paikallisena, nyt muutuja näkyy vain tässä funktiossa
JokinMerkki=KysyMerkki();//funktio palauttaa arvonsa muuttujaan JokinMerkki
TulostaMerkki(JokinMerkki);//Funktio saa parametrinaan JokinMerkki muuttujan arvon
getch();
return 1;
}
Toinen esimerkki
int
LaskeYhteen(int Eka, int Toka)
{
int Summa=0;
Summa=Eka
+ Toka;
return Summa;
}
void main()//pääohjelma
{
int First=4, Second=9,Sum=0;
Sum=LaskeYhteen(First,Second); //Sum nappaa paluuarvon = merkillä
printf("\nsumma on %d",
Sum);
getch();//jäädään
odottamaan, että käyttäjä painaa jotain nappulaa
}
Paluuarvona ei saa palauttaa esimerkiksi osoitteita paikallisiin
muuttujiin, koska ne häviävät funktion päättymisen jälkeen.
Funktion parametrit
Funktioon voidaan sen käynnistyessä viedä tietoa ja se voi päätyttyä
palauttaa kutsujalleen tietoa. Tieto viedään parametrien avulla ja
palautetaan return-käskyn perässä olevalla muuttujalla. Tietoa voidaan
palauttaa joskus myös parametreissa. Funktion muoto Funktion
täydellinen nimi koostuu kolmesta asiasta, paluuarvon tyyppistä,
funktion nimestä ja parametreista.
void TulostaMerkki(char Merkki) //funktion parametrina char tyyppinen muuttuja
{
printf("Antamasi merkki oli %c",Merkki );//tulostetaan annettu merkki %c:n osoittamaan kohtaan
}
int main()
{
char JokinMerkki='a';//esitellään muuttuja, nyt paikallisena, nyt muutuja näkyy vain tässä funktiossa
TulostaMerkki(JokinMerkki); //Funktio saa parametrinaan JokinMerkki muuttujan arvon
getch();
return 1;
}
Toinen esimerkki
void
LaskeYhteen(int Eka, int Toka)
{
int Summa=0;
Summa=Eka
+ Toka;
printf("\nsumma on %d",
Summa);
}
void main()//pääohjelma
{
int First=5, Second=6;
LaskeYhteen(First,Second); //funktion kutsu, kutsussa ja itse
funktiossa muuttujien nimet voivat olla erilaisia
getch();//jäädään
odottamaan, että käyttäjä painaa jotain nappulaa, ei toimi Linuxissa
}
Edellä oleva funktio ottaa parametreikseen muuttujat Eka ja Toka eli
Eka ja Toka vievät tietoa tälle funktiolle. Funktion laskema tulos
näytetään ruudulla, muuta tämä funktio ei palauta mitään tietoa
kutsujalle.
Osoiteparametrit
Kun funktion pitää muuttaa muuttujan arvoa kutsuvassa ohjelmassa, pitää muuttujasta välittää sen osoite eikä muuttujan arvoa.
void
LaskeYhteen(int Eka, int Toka, int *Summa)
//kun muuttujan edessä on * välittyy muututjan arvon sijasta sen osoite
{
*Summa = Eka + Toka;
// * summan edessä aiheuttaa sen ettei osoitteen arvoa muuteta, vaan osoittimen osoittaman muistipaikan sisältö
}
void main()//pääohjelma
{
int First=5, Second=8,Sum=0;
LaskeYhteen(First, Second, &Sum);
//välitetään yhteenlaskettavat arvoparametreina ja summa
osoiteparametrina, jotta summa saadan muutettua nollasta haluttuun
arvoon kutsuttavassa funktiossa
printf("\nsumma on %d",
Sum);
getch();
}
Edellä kuvattu menetelmä vaatii jo hieman huolellisuutta. Aina kun tyypin ja
muuttujan nimen edessä on * merkki, tämä tarkoittaa, että
muuttuja on osoite. Taas * pelkän muuttujan edessä merkitsee
siirtymistä muuttujan osoitteesta muuttujan sisältöön.
* voi tiestysti myös tarkoittaa pelkkää kertomista, onneksi
kääntäjä osaa päätellä tämän.
Merkkijono funktion parametrina
Funktio ei voi palauttaa merkkijonoja eikä taulukoita, vaan näissä
tapuksissa palautetaan aina osoite. Lisäksi osoitteen täyttyy olla
kutsuvan funktion varaama, koska kutsuttavan funktion muuttujavaraukset
häviävät funktiosta palataessa.
void
AnnaNimesi(char OmaNimi[]);
tai
void
AnnaNimesi(char*); //tästä voisi päätellä että kyseessä onkin osoite
void
AnnaNimesi(char OmaNimi[]) //itse asiassa tässä välitetään osoite
merskkijonoon
{
printf("Anna nimesi: ");
gets(OmaNimi); // tässäkin
välitetään merkkijonon osoite
}
void main()//pääohjelma
{
char Nimi[100];
AnnaNimesi(Nimi);//ei tarvita &-merkkiä, koska Nimi on osoite
merkkitaulukkoon Nimi[100]
printf("\nnimi on %s",
Nimi);
getch();
}
Huomaa, että kutsuttava funktio EI määrää
merkkijonon pituutta, ainoastaan kutsuja muuttujan esittelyssä!!!
Vektori funktion parametrina
Vektori on yksiuloitteinen taulukko. Vektori voi sisältää alkioinaan
kaikkia C:n tyyppejä. Funktio ei voi palauttaa, vaan
ainoastaan osoitteen vektorin. Lisäksi osoitteen täyttyy olla kutsuvan
funktion varaama, koska kutsuttavan funktion muuttujavaraukset häviävät
funktoista palataessa.
void Tayta(int* taulu);//esitellä funktio, joka ottaa parametrikseen
osoitteen kokonaislukuun
tai kokonaislukuvektoriin
int main()
{
int Taulu[50];
Tayta(Taulu);
getch();
return 1;
}
void Tayta(int* Vektori)
{
int koko=sizeof(Vektori); //selvitetään
vektorin koko tavuina
int IntinKoko=sizeof(int); //selvitetään
int muuttujankoko tavuina
int JasentenMaara=koko/IntinKoko;
//lasketaan vektorin alkioiden määrä
for(int
i=0;i<JasentenMaara;i++)Vektori[i]=5; // tehdään miltei mahdoton
sijoitusoperaatio
}
Taulukko funktion parametrina
Taulukkossa on enemmän kuin yksi ulottuvuus. Taulukko voi sisältää
alkioinaan kaikkia C:n tyyppejä. Funktio ei voi palauttaa
koko taulukkoa, vaan ainoastaan osoitteen. Lisäksi osoitteen täyttyy
olla kutsuvan funktion varaama, koska kutsuttavan funktion
muuttujavaraukset häviävät funktiosta palattaessa. Ensimmäisen
kokoparametrin voi halutessaan jättää kutsusta pois kts. alla
void Tayta(int taulu[][10],int);
int main()
{
int rivit=5;
int Taulu[5][10];
Tayta(Taulu,rivit);
return 1;
}
void Tayta(int Taulu[][10],int rivit)
{
int i,j;
int sarakkeenkoko=sizeof(*Taulu);
//selvitetään vektorin koko tavuina
int IntinKoko=sizeof(int); //selvitetään
int muuttujankoko tavuina
int
JasenetRivilla=sarakkeenkoko/IntinKoko; //lasketaan vektorin alkioiden
määrä
for(j=0;j<rivit; j++)
for(i=0;i<JasenetRivilla;i++)
Taulu[j][i]=5;// tehdään miltei mahdoton
sijoitusoperaatio
}