Autor: Dondu
Kurs języka C: Spis treści
Poniżej znajdziesz przykłady definiowania i używania funkcji, które pomogą Ci zrozumieć zasady, które poznałeś w temacie Funkcje - definiowanie.
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 realizacja programu rozpoczęła się od tej funkcji. Jeżeli nie zdefiniujesz funkcji main(), to kompilator pokaże 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,
- powinna kończyć się zwróceniem zera (od tej zasady są wyjątki).
Prawidłowo napisana definicja funkcji main( ) wygląda więc 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, którą możesz poznać w artykule: printf().
Funkcja bez argumentów i bez zwracania danej
Przykładem będzie wywołanie funkcji pokaz( ) 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 funkcji 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ą, a funkcja będzie miała za zadanie ją 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; }
Ponieważ funkcja nie będzie niczego zwracała stąd typ funkcji ustawiamy na void.
Program główny zawarty w funkcji main( ) wywoła funkcję pokaz( ) podając jako argument liczbę 5. W ten sposób przekazuje liczbę o wartości 5 do funkcji pokaz( ), która "odbiera" tę liczbę i przypisuje zmiennej lokalnej o nazwie liczba.
Ponownie kompilujemy w CManiak'u i oglądamy rezultat w zakładce Terminal. Możesz oczywiście zmieniać wartości przekazywane w zakresie liczb jakie są możliwe dla typu char, gdyż taki typ nadaliśmy zmiennej liczba.
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. Chcemy żeby po prostu zwróciła nam liczbę np. 53.
Przykład 4 (w kompilatorze)
char podaj_liczbe(void){ return 53; } int main(void) { char wynik; wynik = podaj_liczbe(); printf("%d", wynik); return 0; }
W funkcji main( ) zdefiniowaliśmy sobie zmienną wynik, której przypisujemy wartość zwróconą przez funkcję podaj_liczbe( ), a następnie ją wydrukujemy instrukcją printf( ).
Puszczamy w ruch CManiak'a i obserwujemy rezultat działania 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.
W funkcji wykonamy mnożenie obu argumentów, a wynik zwrócimy do programu ją wywołującego, czyli w tym wypadku do funkcji main( ).
Przykład 5 (w kompilatorze)
int oblicz(char zm1, int zm2){ return zm1 * zm2; } int main(void) { printf("zm1 * zm2 = %d", oblicz(123, 456) ); return 0; }
W porównaniu do przykładu 4, tutaj nie będziemy definiować dodatkowej zmiennej wynik, tylko od razu wykorzystamy zwracaną przez funkcję oblicz( ) wartość do jej wydrukowania funkcją printf( ).
Śmiało testuj w CManiak'u!
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 c.
Funkcja będzie zwracać wynik obliczeń, 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; } 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 tak napisany program 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 silnii danej liczby naturalnej.
W algorytmie wykorzystamy pętlę for(...) { ... }.
Przykład 7 (w kompilatorze)
int silnia(int n) { int k; int wynik = 1; for(k=1; k<=n; k++){ wynik = wynik * k; } return wynik; } int main(void) { printf("silnia = %d \n", silnia(5) ); return 0; }
Zaglądając do tego przykładu w CManiak'u możesz poćwiczyć, by zrozumieć jak działa powyższy program wykorzystujący zdefiniowaną funkcję silnia( ).
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)
char CzyWiekszaOdTysiaca(double liczba) { if(liczba > 1000){ return 1; //sukces (bo jest większa od 1000) }else{ return 0; //niepowodzenie } } int main(void) { printf("%d", CzyWiekszaOdTysiaca(999) ); return 0; }
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)
int main(void) { int a; for(a=997; a<=1010; a++){ if( CzyWiekszaOdTysiaca(a) ){ printf("%d jest większe od 1000 - sukces!!!\n", a); }else{ printf("%d jest mniejsze bądź równe 1000 - niepowodzenie \n", a); } } return 0; }
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: Spis treści
33
Witam.
OdpowiedzUsuńJestem całkowicie początkującym w programowaniu,więc proszę o wyrozumiałość bo pewno to jest banalne albo wręcz "dziwne" pytanie.
Całość jest dla mnie dość przejrzysta tylko nie rozumiem skąd się bierze i co oznacza wpisane w funkcjach oznaczenie np.%d,%f ?
Z tego co się orientuje jest to znak operatora modulo,a jaką rolę pełni w powyższych przykładach?
Witaj. Zobacz w kursie C artykuł dotyczący printf().
UsuńDzięki za szybką odp.
OdpowiedzUsuńWłaśnie już się doczytałem :-)
No cóż moja wina,tak to jest jak się czyta na "raty" :-(
Tak ogólnie to bardzo fajnie,prosto i fachowo napisane poszczególne lekcje kursu,wielki szacunek za tą pracę ! Jak na razie to już nie jest dla mnie tylko "czarna magia".
Pozdrawiam serdecznie.
waldek
To nie Twoja wina. Niektóre tematy się po prostu zazębiają, a od czegoś trzeba zacząć. Tak jest w tym przypadku. Cieszymy się, że kurs się przydaje :-)
UsuńPozdrawiam!
Nie dziala mi pierwsza funkcja w kompilatorze gcc, wyskakuja mi jakies errory "incompatibile implict declaration of built-in function print,
OdpowiedzUsuńSprawdziłem wszystkie przykłady dla tego artykułu, umieszczone w kompilatorze - działają poprawnie. Możesz uściślić problem? Pokaż program, którego kompilacja generuje taki komunikat.
UsuńJuz znalazlem przyczyne, sorry za zamieszanie. Nie umiescilem w programie na poczatku #include , czeski błąd:) pozdrawiam
OdpowiedzUsuńPopraw proszę literówkę "niepowidzenie" w przykładzie 9.
OdpowiedzUsuńM.
Dziękuję za informację - poprawiłem :)
Usuń