...
Code Block |
---|
void KartionTilavuus()
{
float Sade, Korkeus, Tilavuus; // esitellään funktion paikalliset muuttujat
system("cls"); // putsataan ruutu
printf("Lasken kartion tilavuuden"); // annetaan ohjeita käyttäjälle
printf("Anna pohjan säde:");
scanf("%f", &Sade); // kysytään tietoa käyttäjältä
printf("Anna korkeus:");
scanf("%f", &Korkeus);
Tilavuus = 3.14159 * Sade*Sade*Korkeus/3; // lasketaan ja sijoitetaan
printf("Tilavuus on %5.2f", Tilavuus);
}
|
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 muuttujia eli tiedon säilömispaikkoja paikallisia muuttujia (kts. seuraava kohta).
Funktion
...
Funktiota kutsutaan muodossa funktion_nimi() ja sulkujen sisään tulevat mahdolliset parametrit.
Esim funktion kutsuminen pääohjelmasta:
Code Block |
---|
int main() // pääohjelma
{
KartionTilavuus(); // funktion kutsu
getch(); // jäädään odottamaan, että käyttäjä painaa jotain nappulaa
}
|
Note |
---|
Funktiota voidaan kutsua sen mistä tahansa ohjelmasta, myös funktiosta itsestään (vrt. rekursio). |
Funktion parametrit
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äskyllä. Tietoa voidaan palauttaa myös parametreissa (kts. Esimerkki 6 ja Osoittimet).
...
parametrit ja paikalliset muuttujat
Kaikilla funktiolla voi olla omia paikallisia (local) muuttujia. Lisäksi funktiolla voi olla parametreja, joiden avulla funktiolle välitetään tietoa sen ulkopuolelta. Parametrit eroavat paikallisista muuttujista siinä, että niille on annettu alkuarvo funktion kutsussa.
Code Block |
---|
void funktio(int x)
{
int y;
...
}
|
x
on funktion parametri jay
funktion paikallinen muuttuja. On huomattava, että parametrit ja paikalliset muuttujat eivät näy funktion ulkopuolelle eivätkä siten ole käytettävissä muualla kuin funktiossa itsessään.- On myös tärkeää huomata, että eri funktioissa voi olla samannimisiä muuttujia ja ne ovat toisistaan täysin riippumattomia.
Funktion kutsuminen
Funktiota kutsutaan muodossa funktion_nimi() ja sulkujen sisään tulevat mahdolliset parametrit.
Esim funktion kutsuminen pääohjelmasta:
Code Block |
---|
int main( |
...
Esimerkki 2
Code Block |
---|
void TulostaMerkki(char Merkki) // funktionpääohjelma { parametrina char tyyppinen muuttuja { KartionTilavuus(); // printf("Antamasi merkki oli %c", Merkkifunktion kutsu getch(); // tulostetaan annettu merkki %c:n osoittamaan kohtaan } int main() { char JokinMerkki = 'a'; // esitelläänjäädään muuttujaodottamaan, nytettä paikallisena,käyttäjä nytpainaa muutuja näkyy vain tässä funktiossa TulostaMerkki(JokinMerkki); // Funktio saa parametrinaan JokinMerkki muuttujan arvon getch(); return 1; } |
...
jotain nappulaa
}
|
Note |
---|
Funktiota voidaan kutsua sen mistä tahansa ohjelmasta, myös funktiosta itsestään (vrt. rekursio). |
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 2
Code Block |
---|
void TulostaMerkki(char Merkki) // funktion parametrina char tyyppinen muuttuja
{
printf("Antamasi merkki oli %c", Merkki); // tulostetaan annettu merkki %c:n osoittamaan kohtaan
|
...
Esimerkki 3
Code Block |
---|
void LaskeYhteen(int Eka, int Toka) { int Summa = 0; Summa = Eka + Toka; printf("\nsumma on %d", Summa); } int main() { char JokinMerkki = 'a'; // esitellään muuttuja, nyt paikallisena, nyt muutuja näkyy vain //tässä pääohjelmafunktiossa { int First = 5, Second = 6; LaskeYhteen(First, Second);TulostaMerkki(JokinMerkki); // funktionFunktio kutsu,saa kutsussaparametrinaan jaJokinMerkki itsemuuttujan funktiossaarvon muuttujien nimet voivat olla erilaisia! getch(); return 1; } |
Edellä oleva funktio ottaa parametreikseen kaksi kokonaislukua ja sijoittaa ne funktion paikallisiin muuttujiin Eka
ja Toka
. Funktion laskema tulos näytetään ruudulla. Tämä funktio ei palauta mitään tietoa kutsujalle.
Funktion paluuarvo
Funktio voi päätyttyään palauttaa kutsujalleen tietoa. Tieto palautetaan return
-käskyllä. Funktiossa voi olla useita return
-lauseita sopivissa kohdissa. Funktion nimen edessä oleva tyyppi määrää paluuarvon tyypin ja siksi return
-lauseen perässä olevan arvon pitää olla samaa tyyppiä (joko vakio tai muuttuja).
...
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 3
Code Block |
---|
void LaskeYhteen(int Eka, int Toka)
{
int Summa = 0;
Summa = Eka + Toka;
printf("\nsumma on %d", Summa);
}
int main() |
...
Esimerkki 4
Code Block |
---|
#include <stdio.h> #include <conio.h> char KysyMerkki() // funktion tyyppi on nyt char ja funktio paluttaa nyt kutsujalle näppäimistöltä annetun merkin { printf("anna jokin merkki: ")// pääohjelma { int First = 5, Second = 6; return getch(LaskeYhteen(First, Second); // funktion kutsu, kutsussa ja itse funktiossa muuttujien nimet voivat olla erilaisia! // kysytään merkki näppäimistöltä ja palutetaan se funktiosta return lauseella1; } |
Edellä oleva funktio ottaa parametreikseen kaksi kokonaislukua ja sijoittaa ne funktion paikallisiin muuttujiin Eka
ja Toka
. Funktion laskema tulos näytetään ruudulla. Tämä funktio ei palauta mitään tietoa kutsujalle.
Funktion paluuarvo
Funktio voi päätyttyään palauttaa kutsujalleen tietoa. Tieto palautetaan return
-käskyllä. Funktiossa voi olla useita return
-lauseita sopivissa kohdissa. Funktion nimen edessä oleva tyyppi määrää paluuarvon tyypin ja siksi return
-lauseen perässä olevan arvon pitää olla samaa tyyppiä (joko vakio tai muuttuja).
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 4
Code Block |
---|
#include <stdio.h> #include <conio.h> char KysyMerkki() 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; // funktion Esitellääntyyppi muuttuja,on nyt paikallisena,char ja funktio paluttaa nyt muutujakutsujalle näkyynäppäimistöltä vain tässä funktiossa annetun merkin { printf("anna JokinMerkkijokin =merkki: KysyMerkki("); return getch(); // Funktio palauttaa arvonsa muuttujaan JokinMerkki TulostaMerkki(JokinMerkki); // Funktiokysytään saamerkki parametrinaannäppäimistöltä JokinMerkkija muuttujanpalutetaan arvon se funktiosta return 1;lauseella } |
...
Esimerkki 5
Code Block |
---|
int LaskeYhteen(int Eka, int Toka) { void TulostaMerkki(char Merkki) int Summa = 0;// funktion parametrina char tyyppinen muuttuja { Summa = Eka + Toka; return Summa;printf("Antamasi merkki oli %c",Merkki ); // tulostetaan annettu merkki %c:n osoittamaan kohtaan } voidint main() { char JokinMerkki; // Esitellään muuttuja, nyt paikallisena, nyt // pääohjelma { muutuja näkyy vain tässä funktiossa intJokinMerkki First=4, Second=9, Sum=0; Sum = LaskeYhteen(First, Second); KysyMerkki(); // SumFunktio nappaapalauttaa paluuarvonarvonsa =muuttujaan merkilläJokinMerkki printf("\nsumma on %d", SumTulostaMerkki(JokinMerkki); getch(); // Funktio saa parametrinaan JokinMerkki muuttujan arvon return 1; } |
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 5
Code Block |
---|
int LaskeYhteen(int Eka, int Toka) { int Summa = 0; // 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.
Funktio ja osoiteparametrit
Kun funktion pitää muuttaa muuttujan arvoa kutsuvassa ohjelmassa, pitää muuttujasta välittää sen osoite eikä muuttujan arvoa.
Esimerkki 6
...
Code Block |
---|
void LaskeYhteen(int Eka, int Toka, int *Summa) { *Summa = Eka + Toka; Summa = Eka + Toka; return Summa; } void main() // pääohjelma { int First=4, // * summan edessä aiheuttaa sen ettei osiotteen arvoa muuteta, vaan osoittimen osoittaman muistipaikan sisältö } void main() Second=9, Sum=0; Sum = LaskeYhteen(First, Second); // Sum nappaa paluuarvon = merkillä printf("\nsumma on %d", Sum); getch(); // 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. Koska funktion parametrit esitellään nyt muuttujina. Aina kun tyypin ja muuttujan nimen välissä on * merkki, tämä tarkoittaa, että muuttuja on osoite. Taas * pelkän muuttujan nimen edessä merkitsee siirtymistä muuttujan osoitteesta muuttujan sisältöön. * voi tietysti myös tarkoittaa pelkkää kertomista, onneksi kääntäjä osaa päätellä tämän.
Funktion esittely
Funktio esitellään ennen sen käyttöä. Funktion esittelyä sanotaan myös funktion prototyypiksi. Esittely tapahtuu seuraavasti:
Code Block |
---|
int LaskeYhteen(int Eka, int Toka);
|
tai
Code Block |
---|
int LaskeYhteen(int, int);
|
ja
Code Block |
---|
void LaskeYhteen(int *Eka, int *Toka, int *Summa);
|
...
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 prototyyppi (esittely)
Funktio esitellään ennen sen käyttöä. Funktion esittelyä sanotaan myös funktion prototyypiksi. Esittely tapahtuu seuraavasti:
Code Block |
---|
int LaskeYhteen(int Eka, int Toka);
|
tai
Code Block |
---|
int LaskeYhteen(int, int);
|
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ä.
Note |
---|
Funktiot voidaan jättää myös esittelemättä, jos ne on lähdekoodissa ennen pääohjelmaa ja siinä järjestyksessä, että kutsuttava on lähdekoodissa ennen kutsujaa. Tätä tapaa ei kuitenkaan suositella kuin joissain sulautettujen laitteiden ohjelmoinnissa. |
...
Funktio ja osoiteparametrit
Kun funktion pitää muuttaa muuttujan arvoa kutsuvassa ohjelmassa, pitää muuttujasta välittää sen osoite eikä muuttujan arvoa.
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 6
Code Block |
---|
void LaskeYhteen(int Eka, int Toka, int *Summa)
{
*Summa = Eka + Toka; // * summan edessä aiheuttaa sen ettei osiotteen 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. Koska funktion parametrit esitellään nyt muuttujina. Aina kun tyypin ja muuttujan nimen välissä on * merkki, tämä tarkoittaa, että muuttuja on osoite. Taas * pelkän muuttujan nimen edessä merkitsee siirtymistä muuttujan osoitteesta muuttujan sisältöön. * voi tietysti myös tarkoittaa pelkkää kertomista, onneksi kääntäjä osaa päätellä tämän.
Prototyyppi
Code Block |
---|
void LaskeYhteen(int *Eka, int*, int*); |
...
*Toka, int *Summa);
|
tai
Code Block |
---|
void LaskeYhteen(int*, int*, int*);
|
...
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 funktoista palataessa.merkkijonoja eikä taulukoita, vaan näissä tapuksissa palautetaan aina osoite. Täytyy myös ottaa huomioon, se missä merkkijonolle on varattu muisti. Jos se varataan dynaamisesti, se voidaan tehdä funktiossa, mutta jos se varataa staattisesti (ns. normaalisti), se täytyy varata funktion ulkopuolella, koska funktion paikalliset muuttujat tuhoutuvat funktiosta palattaessa.
Prototyyppi:
Code Block |
---|
void AnnaNimesi(char OmaNimi[]); |
...
Code Block |
---|
void AnnaNimesi(char*); // tästä voisi päätellä että kyseessä onkin osoite |
Ja itse funktio:
Code Block |
---|
void AnnaNimesi(char OmaNimi[]) // itse asiassa tässä välitetään osoite merkkijonoon
{
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.
Code Block |
---|
void Tayta(int* taulu); // esitellään funktio, joka ottaa parametrikseen osoitteen kokonaislukuun 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 // ? } |
Taulukko funktion parametrina
Taulukko on useampi- kuin yksiulotteinen taulukko. 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
...