C-kieli‎ > ‎

Funktiot

Yleistä


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.
 
Esim.
         void KartionTilavuus()
         {
              float Sade, Korkeus, Tilavuus; //esitellään 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 paikallisia
muuttujia.

Funktion tehtävät

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.


        void main()//pääohjelma
        {
             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).


Funktion esittely


Funktio esitellään ennen sen käyttöä. Funktion esittelyä sanotaan myös funktion prototyypiksi. Esittely tapahtuu seuraavasti:

        int LaskeYhteen(int Eka, int Toka);
tai
        int LaskeYhteen(int, int);

ja

       void LaskeYhteen(int Eka, int Toka, int *Summa);
tai
       void LaskeYhteen(int, 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ä. 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 käytetään usein sulautettujen laitteiden ohjelmoinnissa.



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
}

Comments