Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

czwartek, 10 lutego 2011

Kurs języka C: Funkcje


Autor: Dondu

Kurs języka C: Spis treści

Funkcje są podstawą języka C!
Są to wydzielone części programu, które wykonują zadane czynności i/lub przetwarzając podane im dane tzw. argumenty. Funkcje po zakończeniu działania mogą (lecz nie muszą) zwracać jakieś dane.

Nawiązując do innych języków funkcje są odpowiednikami podprogramów, czy procedur.

Innymi słowy, to pracownicy specjaliści do określonych małych lub większych zadań. Zaletą funkcji jest możliwość umieszczenia w niej określonej często wykorzystywanej części kodu, a następnie wywoływanie (uruchamianie) funkcji w wielu różnych miejscach programu.

Z punktu widzenia programisty prawie każdy program należy dzielić na mniejsze zadania realizowane w postaci funkcji. W ten sposób program staje się krótki i przejrzysty.


Funkcje są bardzo elastyczne czyli można je definiować i używać na wiele sposobów.


Zanim przejdziemy do przykładów musisz poznać sporo istotnych rzeczy.


Definiowanie funkcji

Aby funkcję "powołać do życia" należy ją zdefiniować w ten sposób:


typ NazwaFunkcji (argumenty) {

    ... jakiś kod do wykonania

}

gdzie:

typ
Określa typ danej jaką zwraca funkcja po jej wykonaniu. Typ danej może być dowolnym typem danych opisanych szczegółowo w temacie: Typy danych


NazwaFunkcji()
Dowolna nazwa jaką sobie wymyślisz jednakże podlegająca takim samym zasadom jak nazwy zmiennych, o których możesz się dowiedzieć w temacie: Zmienne - nazwy i deklaracja

Do nazwy funkcji należy dodać nawiasy (zwykłe) otwierający i zamykający.

W nawiasach tych wpisujemy:

argumenty
To dane przekazywane do funkcji przez program ją wywołujący (nadrzędny). Więcej na ten temat w dalszej części artykułu.


{ }
Nawiasy określające początek i koniec funkcji, czyli blok kodu z którego składa się funkcja. Zasady dotyczące bloków kodu poznasz na przykładzie: Zmienne lokalne blokowe


Oprócz powyższych poznać musisz jeszcze dwa słowa kluczowe void oraz return.

void (ang. pustka, próżnia, pozbawiony czegoś)

To słowo kluczowe oznaczające brak wartości lub po prostu nic. W przypadku funkcji słowo to stosuje się jako:
  • typ funkcji - oznacza wtedy że funkcja nie zwraca żadnej wartości,
  • argument funkcji - oznacza, że funkcja nie ma żadnych argumentów.
Przykłady w dalszej części artykułu.


return;
return JakasDana;

Return służy do:
  • przerwania wykonywania funkcji,
  • przerwania wykonywania funkcji i zwrócenia danej, o typie określonym w czasie definiowania funkcji (typ).
Return może być umieszczony w dowolnym miejscu funkcji lub na jej końcu.
Jeżeli w funkcji nie ma słowa return, to po dojściu do końca funkcji następuje wyjście z niej tak jakby wykonano return bez podania zwracanej danej.





Przejdźmy więc do meritum tematu. Zaczniemy jednakże od specyficznej funkcji, którą jest funkcja main() ponieważ będzie nam potrzebna w każdym przykładzie:

main()

To funkcja, od której wywołania (uruchomienia) zaczyna się wykonywanie napisanego programu.

W trakcie kompilowania, kompilator szuka funkcji main() i przygotowuje kod wynikowy w taki sposób, by od realizacja programu rozpoczęła się od tej funkcji. Jeżeli nie zdefiniujesz funkcji main(), to kompilator pokażę błąd kompilacji i przerwie ją.

Ponieważ funkcja main() jest wyjątkiem podlega więc szczególnym zasadom i powinna być zawsze definiowana w następujący sposób:
  • musi być typu int,
  • nie może mieć argumentów,
  • musi kończyć się zwróceniem zera.

Prawidłowo napisana definicja funkcji main() wygląda tak:

Przykład 1 (w kompilatorze)
int main(void){

   return 0;
}

W kompilatorze CManiak znajdziesz ten przykład. Skompiluj w wersji takiej jak jest, by sprawdzić jakie kompilator pokaże komunikaty.




Teraz zdefiniujemy sobie różne funkcje, którym wyznaczymy jakieś zadania do zrealizowania. Aby zobaczyć rezultaty posługiwać się będziemy funkcją drukowania printf().


Funkcja bez argumentów i bez zwracania danej

Przykładem będzie wywołanie funkcji w celu wydrukowania napisu w niej zawartego.

Przykład 2 (w kompilatorze)
void pokaz(void){
  printf("a ten drugi.");
}


int main(void)
{
  printf("Ten napis jest pierwszy, \n");
  pokaz();
  return 0;
}

Program rozpocznie się od wykonania funkcji main( ), która najpierw wydrukuje napis pierwszy, a później wywoła funkcję pokaz( ), która wydrukuje napis drugi.

Zauważ, że w przypadku funkcji pokaz( ) jako typ oraz argument podaliśmy void, czyli:
  • funkcja nie będzie niczego zwracać,
  • nie przekazujemy funkcji żadnych danych.

Skompiluj powyższy przykład w kompilatorze CManiak i zobacz rezultaty w zakładce Terminal.


Funkcja z argumentem, ale bez zwracania danej

Teraz przekażemy funkcji jakąś daną, którą będzie miała wydrukować. Do zapamiętania danej w funkcji pokaz( ) użyjemy zmiennej, którą nazwiemy liczba. Przyjmijmy, że dana ta będzie typu char.


Przykład 3 (w kompilatorze)
void pokaz(char liczba){
  printf("%d", liczba);
}

int main(void)
{
  printf("Ilość krów w oborze = ");
  pokaz(5);
  return 0;  //zakończ wykonywanie programu
}

I ponownie kompilujemy w CManiak'u i oglądamy rezultat w zakładce Terminal.




Funkcja bez argumentów, ale zwracająca daną


Czas na funkcję, która zwróci nam jakąś wartość. Na razie funkcji nie podamy żadnego argumentu.

Przykład 4 (w kompilatorze)
//definiujemy funkcję podaj_liczbe() która:
// - będzie zwracała liczbę typu char
// - nie wymaga podania żadnych argumentów
char podaj_liczbe(void){

  return 53;  //zakończ wykonywanie funkcji zwracając liczbę 53
  
}

//program zaczyna się od funkcji main()
int main(void)
{

  //wydrukuj liczbę którą zwróci funkcja 
  printf("%d", podaj_liczbe() );
  
  return 0;  //zakończ wykonywanie programu
}


Funkcja z argumentami i zwracająca daną

Teraz zbudujemy funkcję z dwoma argumentami (jeden typu char, drugi typu int) oraz oczekiwać będziemy, że funkcja zwróci liczbę typu int.


Przykład 5 (w kompilatorze)
//definiujemy funkcję oblicz() typu int  
//z dwoma argumentami typu char oraz int 
int oblicz(char zm1, int zm2){

  return zm1 * zm2;  //zwróć wynik mnożenia argumentów
  
}

//program zaczyna się od funkcji main()
int main(void)
{
  
  //pokaż napis
  printf("zm1 * zm2 = %d", oblicz(123, 456) );
  
  return 0;  //zakończ wykonywanie programu
}






Przykłady z życia wzięte


Aby poćwiczyć wykorzystanie funkcji zdefiniujemy funkcję, która będzie odpowiedzialna za obliczanie wyniku funkcji kwadratowej (matematyka) dla podanych liczb jako argumentów wywołania funkcji.


W języku C nie ma operatora arytmetycznego podnoszącego liczbę do kwadratu, więc po prostu pomnożymy x przez siebie, czyli:


Nasza funkcja wymagać będzie podania argumentów: x, a, b oraz zwracając wynik obliczenia czyli y.

Abyśmy mogli wypróbować w kompilatorze jak liczy nasza funkcja na liczbach zmiennoprzecinkowych, wszystkie zmienne oraz funkcja będą typu double.

Przykład 6 (w kompilatorze)
double FunkcjaKwadratowa(double x, double a, double b, double c )
{
  double y;
  y = a*x*x + b*x + c;
  return y;  //zwróć wynik
}

int main(void)
{
  printf("y = %f \n", FunkcjaKwadratowa(102, 0.5, 10, 100) );
  return 0;
}

W kompilatorze CManiak czeka na ciebie przykład wraz z komentarzami. Wypróbuj jak działa powyższy przykład i wstawiaj swoje liczby. Pamiętaj, że przecinek oddziela argumenty, a kropka oddziela część całkowitą liczby od części ułamkowej.


Drugi przykład z życia wzięty to liczenie silni danej liczby naturalnej.


W algorytmie wykorzystamy pętlę for(...) { ... }.


Przykład 7 (w kompilatorze)
//definiujemy funkcję silnia() typu int (liczby całkowite)
//z jednym argumentem n typu int
int silnia(int n)
{
  int k;                 //zmienna pomocnicza
  int wynik=1;           //zmienna przechowująca wynik liczenia silnii
  
  //pętla licząca silnię
  for(k=1; k<=n; k++){   
     wynik = wynik * k;
  }
  
  return wynik;  //zwróć wynik
}


//program zaczyna się od funkcji main()
int main(void)
{
  printf("silnia = %d \n", silnia(5) );   //pokaż silnię dla liczby 5
  return 0;  //zakończ wykonywanie programu
}

I znowu zaglądając do tego przykładu w CManiak'u możesz poćwiczyć rozumienie tego przykładu użycia funkcji w języku C.





Sukces vs niepowodzenie

Pisząc swoje programy powinieneś używać pewnego standardu określania, czy działanie funkcji zostało zakończone sukcesem czy niepowodzeniem.

Chodzi o takie funkcje które nie zwracają wyniku jako takiego, ale wykonują jakieś czynności i chcą powiadomić program który je wywołał, że wykonały zadanie z sukcesem lub niepowodzeniem.

Sukces powinieneś definiować jako 1, a niepowodzenie jako 0.

Najprościej zrozumieć to jest poprzez przykład.


Przykład 8 (w kompilatorze)
//definiujemy funkcję CzyWiekszaOdTysiaca() typu char
//z jednym argumentem liczba typu double
char CzyWiekszaOdTysiaca(double liczba)
{
  //sprawdzamy czy liczba jest większa od tysiąca
  if(liczba > 1000){
    return 1;    //sukces (bo jest większa od 1000)
  }else{
    return 0;    //niepowodzenie
  }
}


//program zaczyna się od funkcji main()
int main(void)
{
  //sprawdź liczbę
  printf("%d", CzyWiekszaOdTysiaca(999) );
  return 0;  //zakończ wykonywanie programu
}

Takie podejście definiowania sukcesu i niepowodzenia pozwala na łatwe wykorzystanie podczas sprawdzania warunków instrukcjami warunkowymi.

I znowu skorzystamy z CManiaka by zobaczyć jak to ułatwia pisanie kodu. Wykorzystamy funkcję CzyWiekszaOdTysiaca() zdefiniowaną w poprzednim przykładzie, ale wynik jej działania wykorzystamy tak:

Przykład 9 (w kompilatorze)
//program zaczyna się od funkcji main()
int main(void)
{
  int a;    //deklaracja zmiennej, którą będziemy sprawdzać
  
  //zaczniemy dla a=997 a skończymy na a=1010 
  //zwiększając a o jeden za każdym krokiem pętli for()
  for(a=997; a<=1010; a++){

    //sprawdzamy czy a jest większe od 1000 wywołując 
    //funkcję i podając jako argument zmienną a
    if( CzyWiekszaOdTysiaca(a) ){
      
      //gdy jest sukces
      printf("%d jest większe od 1000 - sukces!!!\n", a);
      
    }else{
      
      //gdy jest niepowodzenie
      printf("%d jest mniejsze bądź równe 1000 - niepowidzenie \n", a);
      
    }
  }
  return 0;  //zakończ wykonywanie programu
}





Podsumowanie

Funkcje są bardzo elastycznymi fragmentami programu, które mogą spełniać przeróżne zachcianki programisty. Bardzo ważne jest by opanować pisanie funkcji do perfekcji, bo znacząco ułatwi Ci to dzielenie programu na spójne fragmenty, a później składanie z nich całego programu. W ten sposób programy stają się krótkie, czytelne i co najważniejsze łatwo i szybko można je modyfikować.

Co więcej, dobrze napisane funkcje można często wykorzystywać w innych programach, co znacząco przyspiesz ich pisanie.

Jeżeli czegoś nie rozumiesz, śmiało zadawaj pytania w komentarzach.

Kurs języka C: Tips & Tricks - Spis treści
Kurs języka C: Spis treści

33
Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

2 komentarze:

  1. Nie rozumiem przykładu nr4. Tyle pisania żeby otrzymać liczbę którą i tak założyliśmy że zostanie zwrócona? Nie wystarczyło napisać by wyświetlić liczbę 53?


    #include
    int main(void)
    {
    printf("A nie można było tak:\n \n");
    printf("Tu wpisuję liczbę 53.");
    return 0;
    }

    OdpowiedzUsuń
  2. Przykład nr 4 zatytułowany jest: Funkcja bez argumentów, ale zwracająca daną
    i opisany co chcemy osiągnąć.

    Celem tego przykładu jest pokazanie jak wywołać funkcję, która zwróci jakąś wartość. Pokazałem najprostszy przykład, ale przecież w funkcji mogą być skomplikowane obliczenia i wile linijek kodu. Będzie taki przykład w dalszej części tego artykułu, gdy go już skończę :-)

    OdpowiedzUsuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.