4. Funkcje Przykłady 4.1. Napisz funkcję kwadrat, która przyjmuje jeden argument: długość boku kwadratu i zwraca pole jego powierzchni. Używając tej funkcji napisz program, który obliczy pole powierzchni kwadratu o boku 5. 4 int kwadrat (int n) { 5 return n*n; 9 cout << kwadrat(5) << endl; 10 11 return 0; 12 } W pierwszym rozdziale nauczyliśmy się wykorzystywać wbudowane w język C++ funkcje matematyczne znajdujące się w pliku cmath, takie jak sqrt czy pow. W tym rozdziale nauczymy się definiować własne funkcje i wykorzystywać je w programach. W liniach 4-6 umieszczona została definicja funkcji kwadrat, która przyjmuje jeden argument (liczbę całkowitą n), a następnie oblicza i zwraca wartość kwadratu tej liczby. Definicja funkcji składa się z 4 elementów, kolejno: typu zwracanego, nazwy funkcji, listy argumentów i ciała funkcji. Typ zwracany (tutaj int) określa typ wartości, która jest wynikiem działania naszej funkcji. W tym przykładzie operujemy na liczbach całkowitych, stąd typem zwracanym jest int. Następnie nazwa funkcji (kwadrat), której będziemy później używać do wywoływania danej funkcji. Ograniczenia nazw funkcji są takie same jak dla zmiennych: małe i wielkie litery alfabetu angielskiego, cyfry i znaki podkreślenia, przy czym nazwa nie może zaczynać się od cyfry. Istotne jest także to, że nie możemy mieć jednocześnie zmiennej i funkcji o tej samej nazwie. 24
Po nazwie, w nawiasach okrągłych, znajduje się lista argumentów. Każdy argument posiada typ oraz nazwę, a kolejne argumenty oddzielone są przecinkami. Tutaj posiadamy tylko jeden argument: n, który posiada typ int. W końcu w nawiasach klamrowych umieszczamy ciało funkcji, czyli kod, który zostanie wykonany w momencie wywołania naszej funkcji. Istotne są tutaj dwie rzeczy. Po pierwsze, ciało funkcji powinno zawierać wyrażenie return (linia 5), które zwraca wynik działania funkcji i kończy jej działanie. Po drugie, argumenty funkcji możemy wykorzystywać wewnątrz ciała funkcji jak zmienne. Ich początkowe wartości będą równe tym, które przekazane zostały w wywołaniu funkcji. Przykład wywołania funkcji kwadrat znajduje się w linii 9. Tak jak w przypadku wbudowanych funkcji matematycznych, podajemy najpierw nazwę funkcji (kwadrat), a następnie w nawiasach okrągłych wartości przekazywanych argumentów. Tutaj przekazujemy tylko jedną wartość 5, która zostanie przypisana argumentowi n wewnątrz funkcji kwadrat. 4.2. Napisz funkcję wartosc_bezwzgledna, która przyjmuje jeden argument: liczbę całkowitą, a zwraca wartość bezwzględną tej liczby. Napisz program, który obliczy wartość bezwzględną liczby -42 używając tej funkcji. 4 int wartosc_bezwzgledna(int n) { 5 if (n > 0) { 6 return n; } else { 8 return -n; 9 } 10 } 11 12 int main() { 1 cout << wartosc_bezwzgledna(-42) << endl; 14 15 return 0; 1 Funkcje zawierać mogą nie tylko wyrażenia return, ale dowolny inny kod. Możemy w nich tworzyć nowe zmienne, wypisywać i pobierać dane, sprawdzać warunki oraz wykorzystywać wszystkie inne konstrukcje języka C++, jak pętle (o których dowiemy się nieco później). Dodatkowo funkcja może zawierać więcej niż jedno wyrażenie return. Istotne jest jedynie to, że zawsze wykonane zostanie tylko jedno z nich: to, do którego 25
program dotrze w pierwszej kolejności. Następnie funkcja zakończy swoje działanie, a jakikolwiek inny kod znajdujący się wewnątrz funkcji zostanie zignorowany. W ten sposób, jeżeli do funkcji wartosc_bezwzgledna przekażemy liczbę dodatnią, warunek z linii 5 będzie spełniony i wykona się wyrażenie return z linii 6, które zwróci oryginalną wartość argumentu, po czym działanie funkcji zakończy się. W przeciwnym wypadku, jeżeli argument będzie ujemny (lub zero), wykona się wyrażenie z linii 8, zwrócona zostanie wartość przeciwna do danej i działanie funkcji zakończy się. Uwaga! W C++ umieszczenie kolejnych linii kodu bezpośrednio po wyrażeniu return nie jest błędem taki program uruchomi się. Jednakże kod znajdujący się za tym wyrażeniem nigdy nie zostanie wykonany, ponieważ wyrażenie return kończy działanie funkcji. 4.. Napisz funkcję delta, która przyjmuje trzy argumenty: współczynniki a, b, c równania kwadratowego, a zwraca wartość delty tego równania. Napisz program, który obliczy deltę równania x 2 2x + 1 = 0 używając tej funkcji. 4 double delta(double a, double b, double c) { 5 return b*b - 4*a*c; 9 cout << delta(1, -2, 1) << endl; 10 11 return 0; 12 } Funkcja może zwracać każdy z możliwych typów zmiennej, w tym także typ double. Argumenty także mogą przyjmować dowolny typ zmiennej. Jeżeli chcemy, aby funkcja przyjmowała więcej niż jeden argument, w definicji funkcji umieszczamy je wszystkie, każdy z własnym typem i nazwą, oddzielone przecinkami. Ich kolejność jest istotna: wartości przekazywane do funkcji będą przypisywane do argumentów w takiej kolejności, w jakiej argumenty były podane w definicji funkcji. W ten sposób wywołanie funkcji delta w linii 9 przypisze wartość 1 argumentowi a, wartość -2 argumentowi b i wartość 1 argumentowi c. 26
4.4. Napisz funkcję czy_wieksza, która sprawdzi czy pierwsza z dwóch pobranych liczb jest większa od drugiej. Napisz program, który przy jej użyciu sprawdzi, czy liczba 5 jest większa od 6. 4 bool czy_wieksza(int a, int b) { 5 return a > b; 9 if (czy_wieksza(5, 6)) { 10 cout << "Jest wieksza" << endl; 11 } else { 12 cout << "Nie jest wieksza" << endl; 1 } 14 15 return 0; 1 Funkcje mogą zwracać również wartości logiczne, co pozwala na łatwe sprawdzenie prawdziwości skomplikowanych warunków. Aby uzyskać taki efekt, potrzebny jest nam nowy typ zmiennej: bool. Jest to typ logiczny, który przyjmuje jedną z dwóch wartości: true (prawda) lub false (fałsz). Każdy warunek w rzeczywistości jest operatorem (takim jak + czy -), którego wynikiem działania jest jedna z dwóch wartości logicznych. Możemy wynik takiego działania przechowywać w zmiennej (typu bool), przekazywać jako argument czy zwracać jako wynik działania funkcji (linia 5). Wyrażenie warunkowe tak naprawdę przyjmuje wartość logiczną, czyli oprócz warunków przy użyciu operatorów porównania możemy użyć także wartości true i false, zmiennych typu bool czy wywołań funkcji o typie zwracanym bool (linia 9). Uwaga! W miejscu warunku w wyrażeniu warunkowym if możemy także użyć liczby. Każda liczba różna od zera ma wartość logiczną true, a zero posiada wartość false. Podobnie w drugą stronę, użycie wartości logicznej jako liczby również jest dopuszczalne. Wartość false da nam 0, natomiast true zostanie zamienione na 1. 2
4.5. Napisz funkcję hello_world, która wypisze na ekran słowa Hello, world!. Napisz program, który wypisze na ekran te słowa używając tej funkcji. 4 void hello_world() { 5 cout << "Hello, world!" << endl; 9 hello_world(); 10 11 return 0; 12 } Możliwe jest napisanie funkcji, która nie zwraca żadnej wartości ani nie przyjmuje żadnych argumentów. Jeżeli nie chcemy, żeby nasza funkcja przyjmowała jakiekolwiek argumenty, w definicji pozostawiamy jej listę argumentów pustą (linia 4). Nawiasy okrągłe muszą jednak pozostać na swoim miejscu. Podobnie wywołanie funkcji wciąż zachowuje okrągłe nawiasy po nazwie funkcji, jednak nie umieszczamy między nimi żadnej wartości. Jeżeli nie chcemy zwracać żadnej wartości, typ zwracany zastępujemy w definicji słowem void. W tym wypadku możemy pominąć w ciele funkcji wyrażenie return, jako że żadna wartość nie będzie zwracana. Działanie funkcji zakończy się w momencie dotarcia do ostatniej linii ciała funkcji. Umieszczenie wyrażenia return w funkcji typu void jest jednak dopuszczalne w celu wymuszenia wcześniejszego zakończenia jej działania. W takim wypadku jednak pomijamy wartość zwracaną po słowie return i umieszczamy bezpośrednio po nim średnik. Pytania 4.1. Co wypisze na ekran wywołanie f(5)? 1 int f(int n) { 2 return *n-5; cout << "f(n) = " << *n-5 << endl; 4 } 28
4.2. Co wypisze na ekran wywołanie g(-5)? 1 int g(int n) { 2 if (n > 0) { return n; 4 } 5 6 cout << "Dana liczba jest ujemna" << endl; return -n; 8 } 4.. Jak różnią się w zachowaniu funkcje oblicz_kwadrat i wypisz_kwadrat zdefiniowane poniżej? 1 int oblicz_kwadrat(int n) { 2 return n*n; } 4 5 void wypisz_kwadrat(int n) { 6 cout << n*n << endl; } 4.4. Gdybyśmy chcieli napisać programy obliczające kwadrat danej liczby, każdy wykorzystujący inną funkcję z poprzedniego pytania, czym różniłyby się te programy? 4.5. Co wypisze na ekran następujący fragment kodu? 1 if (false) { 2 cout << "A" << endl; } else { 4 cout << "B" << endl; 5 } Zadania 4.1. (+0) Napisz funkcję, która przeliczy daną odległość w kilometrach na mile. Napisz program, który będzie dokonywać przeliczenia przy użyciu tej funkcji. 4.2. (+0) Napisz funkcję, która przeliczy daną temperaturę w stopniach Fahrenheita na stopnie Celsjusza (C = 5 9 (F 2)). Napisz program, który przeliczać będzie daną przez użytkownika temperaturę przy użyciu tej funkcji. 29
4.. (+0) Napisz funkcję, która obliczy i zwróci pole koła o zadanym promieniu. 4.4. (+40) Napisz funkcję, która obliczy pole powierzchni stożka o zadanej wysokości i promieniu podstawy. 4.5. (+40) Napisz funkcję, która dla danej liczby całkowitej zwróci połowę jej wartości (jeżeli dana liczba jest parzysta) lub jej trzykrotność zwiększoną o 1 (jeżeli jest nieparzysta). 4.6. (+0) Napisz funkcję, która zwróci mniejszą z dwóch danych liczb. 4.. (+40) Napisz funkcję, która zwróci najmniejszą z trzech danych liczb. 4.8. (+40) Napisz funkcję signum, która zwracać będzie wartość funkcji signum danej liczby. Napisz program, który wykorzysta tę funkcję do obliczenia wartości funkcji signum dla danej przez użytkownika liczby. 4.9. (+0) Napisz funkcję, która sprawdzi, czy dana liczba jest dzielnikiem drugiej. Napisz program, który przy jej użyciu będzie dla danych przez użytkownika liczb będzie wypisywać słowo tak lub nie, w zależności od tego, czy pierwsza z liczb dzieli drugą czy nie. 4.10. (+40) Napisz funkcję, który sprawdzi, czy z odcinków o danych długościach boków da się zbudować trójkąt. Napisz program, który przy użyciu tej funkcji sprawdzi, czy z odcinków o długościach 1, 2 i da się zbudować trójkąt. 4.11. (+40) Napisz funkcję, która sprawdzi, czy trójkąt o zadanych bokach jest prostokątny. Napisz program, który przy użyciu tej funkcji sprawdzi, czy trójkąt o długościach boków 12, 1 i 5 jest prostokątny. 4.12. Rozwiąż zadania z poprzednich rozdziałów, tym razem pisząc odpowiednie funkcje, a następnie programy wykorzystujące te funkcje. Rozszerzenie 4.1. (+10) Napisz funkcję suma, która obliczy i zwróci sumę liczb znajdujących się w danej tablicy (lub wektorze). 4.2. (+210) Napisz funkcję licznik, która nie przyjmuje argumentów, a każde kolejne jej wywołanie zwraca kolejne liczby naturalne. Pierwsze wywołanie tej funkcji powinno zwrócić 0, kolejne 1, następne 2 itd. 4.. (+40) Napisz funkcję zlicz, która przyjmie od użytkownika pewien ciąg liczb całkowitych (w postaci tablicy lub wektora) oraz wskaźnik do funkcji, która przyjmuje liczbę całkowitą, a zwraca wartość logiczną. Funkcja ta ma policzyć dla ilu elementów danego ciągu dana funkcja zwraca prawdę. 0