Rozdział 10 Funkcje. Komunikacja przez wartość i przez referencję.
Celem rozdziału jest zapoznanie Studentów z różnymi możliwościami komunikacji programu z funkcją. Zostaną tu omówione dwa sposoby przekazywania argumentów do funkcji: przekazywanie argumentów przez wartość oraz przez referencję.
10.1. Przesyłanie argumentów do funkcji przez wartość.
W przypadku wywołania funkcji z przekazywaniem argumentu przez wartość, w funkcji wykonywana jest kopia lokalna podanego argumentu. Wywołana funkcja wykonuje swoje operacje na utworzonej kopii. Po zakończeniu działania funkcji, kopia lokalna jest niszczona. A zmiany dokonane na zmiennych wewnątrz funkcji nie są zapisane.
Przypomnijmy deklarację oraz wywołanie funkcji
Nagłówek funkcji:
- typ nazwa_funkcji(parametry formalne)
Wywołanie:
- nazwa_funkcji(parametry aktualne)
Parametrem formalnym może być tylko lista zmiennych z typami, oddzielona przecinkami. Parametrem aktualnym natomiast może być zmienna, literał lub wyrażenie np. (1+3,a-b…)
Na przykładzie zobaczmy sposób przekazywania dwóch parametrów do funkcji przez wartość.
Listing 10.1. Tekst programu pokazującego komunikację programu z funkcją poprzez wartość.
Dokonajmy analizy powyższego programu. Na początku deklarujemy i definiujemy funkcję o nazwie fun( int a, int b). Jak widzimy do funkcji są przekazywane dwa parametry a i b są to parametry formalne funkcji, czyli parametry dla których funkcja utworzy sobie lokalnie kopie w pamięci komputera i na tych kopiach będzie pracowała. W funkcji wypisujemy wprowadzone dane, czyli a i b, oraz dokonujemy zmiany wartości tych zmiennych i ponownie wypisujemy na ekranie monitora wartości a i b. W programie natomiast dokonujemy deklaracji zmiennych a i b ( to nic, że zmienne nazywają się tak samo, mają one różne lokalizacje w pamięci komputera), wypisujemy na monitorze wartości zmiennych a i b a następnie wywołujemy funkcję z parametrami aktualnymi a i b i ponownie wypisujemy na monitorze wartości zmiennych a i b.
Zauważmy, jaki wynik otrzymamy po uruchomieniu podanego przykładu.
Rys 10.1 Wynik działania programu z listingu 10.1
Zauważmy, że po wyjściu z funkcji fun() wartości zmiennych a i b nie zmieniły się, gdyż w funkcji fun() przesyłamy tylko wartość liczbową zmiennych a i b ( parametrów aktualnych). Wartości te służą do inicjalizacji parametru formalnego, czyli zmiennej lokalnej funkcji. Jest to jakby zrobienie sobie kopii w obrębie funkcji. Dalej funkcja pracuje na tej kopii. Czyli w naszym przykładzie zmiana wartości lokalnych zmiennych a i b nie nastąpiła do komórek pamięci, gdzie są zapisana zmienna a i b ( z programu głównego) ale do komórek pamięci gdzie są zapisane te zmienne lokalne (czyli kopie). Po opuszczeniu funkcji ta kopia zostaje usunięta. Gdybyśmy nie wypisywali poszczególnych kroków na monitorze to nie mielibyśmy śladu, że funkcja cos zrobiła, tym bardziej, że funkcja jest typu VOID ( nieokreślony).
10.2.Przesyłanie argumentów do funkcji przez referencję( przez zmienną).
Jeżeli chcemy, aby funkcja dokonała nam jakichś obliczeń, które będziemy mogli wykorzystać w dalszej pracy to powinniśmy utworzyć funkcję o określonym typie np. int, float, char itd., Jeśli natomiast chcemy, aby zostały dokonane zmiany na argumentach przesyłanych do funkcji to powinniśmy skorzystać z komunikacji programu z funkcją za pomocą referencji.
Określmy deklarację oraz wywołanie funkcji
- typ nazwa_funkcji(¶metry formalne) //uwaga na &
przykład: void zamien(int &a,int &b)
Wywołanie:
- nazwa_funkcji(parametry aktualne)
Przykład: zamien(c,d)
W przypadku komunikacji programu z funkcją za pomocą referencji przesyłamy do funkcji adres zmiennej w pamięci komputera a nie wartość zmiennej. Nawet, jeśli parametry formalne i aktualne mają różne nazwy to oznaczają ten sam obiekt i wszelkie zmiany dokonane wewnątrz przez funkcję będą widoczne również po wyjściu z funkcji ( analogia do przekazywania argumentów do funkcji za pomocą wskaźnika).
Zobaczmy sposób komunikacji programu z funkcją za pomocą referencji na poniższym przykładzie.
Listing 10.2. Tekst programu pokazującego komunikację programu z funkcją poprzez referencję.
Rys 10.2 Wynik działania programu z listingu 10.2
Analizując program zwróćmy uwagę na znak & (ampersand) stojący przy parametrach formalnych w funkcji oraz zauważmy, że tym razem po opuszczeniu funkcji, zmiany jakie zostały dokonane wewnątrz funkcji, są widoczne nawet po opuszczeniu funkcji.
Wniosek !
Przesyłanie argumentów funkcji przez referencję pozwala na modyfikowanie zmiennych ( nawet lokalnych) znajdujących się poza tą funkcją.
Wyjątek tutaj stanowi przesyłanie do funkcji tablicy, zawsze zmiany dokonane na tablicy wewnątrz funkcji będą widoczne również po opuszczeniu funkcji.
10.3. Przekazywanie do funkcji tablic
Jak wiemy już z poprzedniego rozdziału do funkcji można przekazywać również tablice. Przekazywanie tablic odbywa się zawsze ( niezależnie od zapisu) przez referencje – funkcja otrzymuje adres pierwszego elementu przekazywanej tablicy.
Jako parametr formalny możemy wpisać np. tab[], możemy podać samą nazwę tablicy- tab, gdyż jak pamiętamy nazwa tablicy jest adresem jej pierwszego elementu oraz użyć wskaźnika (Rozdział 9).
Zatem każdy z poniższych zapisów jest prawidłowy i daje ten sam efekt.
void funkcja(float tab, int N) lub
void funkcja(float *tab, int N)
void funkcja(float tab[], int N)
Poniższy przykład ilustruje wyświetlanie tablicy o dowolnej długości.
Listing 10.3. Tekst programu pokazującego przekazywanie do funkcji tablic.
Rys 10.3 Wynik działania programu z listingu 10.3
10.4. Zadania na „ Laboratorium programowania ”
- Napisz program, który obliczy iloczyn dwu prostokątnych macierzy. Ponadto program ma przekazać przez referencję wartość 1, gdy mnożenie jest wykonywalne i -1 w przeciwnym razie.
- Napisz program dodający do siebie dwie macierze o jednakowych wymiarach. Na ekranie mają być wyświetlone trzy macierze: A, B, A+B. Losowanie danych do macierzy A i B, następnie dodawanie i wyświetlanie należy zrealizować w oddzielnych funkcjach. Macierze( tablice dwuwymiarowe) są przekazywane, jako parametry do funkcji, rozmiar macierzy ( wprowadzany przez użytkownika w funkcji wczytywania danych) przekazujemy do funkcji za pomocą referencji.
- Napisz funkcję wyświetlającą dowolny wiersz i kolumnę z macierzy. Numer wiersza lub kolumny ma być podawany przez użytkownika ( przekazywany do funkcji za pomocą referencji) i powinien znajdować się w zadanym przez programistę zakresie.
- Napisz funkcję logiczną, która sprawdzi czy liczba podana parametrem jest palindromem. Wykorzystaj ją w funkcji, która przez nazwę funkcji zwraca ilość palindromów w n-elementowej tablicy liczb, a poprzez referencję indeks pierwszego palindromu w tablicy. Gdy w tablicy brak jest palindromów funkcja zwraca 0, a wskaźnik na pierwszy palindrom równa sie NULL.
WEJSCIE:
n=4
523
1234321
576
323
WYJSCIE:
2
1
- Napisz funkcję, która odnajdzie w tablicy przekazanej jako parametr funkcji liczby podzielne przez liczbę x, również zadaną jako parametr tej funkcji, a następnie zwiększy je y-krotnie (y też jest parametrem funkcji). Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, która w tablicy znaków zadanej jako parametr funkcji zamieni małe litery na wielkie i odwrotnie. Następnie napisz program, w który wywoła tą funkcję.
- Napisz funkcję, która w tablicy dwuwymiarowej n x m przekazanej jako parametr funkcji, w każdym wierszu podanej macierzy odszuka element maksymalny. Funkcja powinna zwracać dwie wartości: liczbę maksymalną oraz numer kolumny (skorzystaj z przekazywania danych za pomocą referencji).
- Dany jest przedział liczb naturalnych (podany przez użytkownika). Napisz funkcję, która wylosuje kilka liczb z podanego przedziału oraz funkcję, która sprawdzi czy wylosowane liczby są liczbami pierwszymi. Zaimplementuj wyznaczanie liczb pierwszych przy pomocy funkcji: int pierwsze(int a); a – liczba przekazana do funkcji sprawdzającej czy jest liczbą pierwszą. Funkcja zwraca wartość 0 gdy liczba nie jest liczbą pierwsza, 1 w przeciwnym przypadku (gdy jednak jest). Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję szukającą liczb bliźniaczych w zadanym przedziale <x1,x2>.
Liczby bliźniacze to 2 liczby pierwsze oddalone od siebie o 2, np: 3,5; 5,7. Zaimplementuj sprawdzanie czy liczby są bliźniacze przy pomocy funkcji: void blizniacze(int x1, int x2); //funkcja ta znajduje i wypisuje liczby bliźniacze. wewnątrz niej następuje wywołanie funkcji pierwsze. Następnie napisz program, który wywoła tą funkcję.
10.5. Zadania do samodzielnego rozwiązania
- Napisz funkcję, która wyświetli postać binarną liczby całkowitej podanej jako parametr zapisanej w systemie dziesiętnym. Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, która dla dwóch dodatnich całkowitoliczbowych argumentów m i n zwraca wartość true jeżeli n dzieli m oraz false w przeciwnym wypadku. Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, która dla nieujemnej liczby n, takiej, że 0≤n≤20 wyznaczy dwusilnię.
Uwaga ! Dwusilnię dla dowolnej liczby naturalnej n wyznaczamy według wzoru:
Przykład: 5!!=5⋅3⋅1=15 oraz 6!!=6⋅4⋅2=48
- Napisz funkcję, która zwróci 1, w przypadku, gdy suma cyfr danej liczby, oraz suma cyfr tej liczby w notacji binarnej będzie taka sama w przeciwnym wypadku zwróci 0. Wyświetl wszystkie liczby z przedziału <n, m>, gdzie n i m podajemy z klawiatury, które spełniają podane kryterium. W zadaniu wykorzystaj trzy funkcje:
- funkcja zwracająca sumę cyfr w systemie dziesiętnym
- funkcja zwracająca sumę cyfr w systemie binarnym
- funkcja zwracająca 1 lub 0, w zależności od spełnienia kryteriów
- Napisz funkcję, która sprawdzi, czy podana, jako parametr liczba całkowita jest sześcianem pewnej liczby naturalnej. Funkcja powinna zwracać wartość 1, jeśli liczba spełnia warunek oraz 0 w przeciwnym wypadku. Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, która wyznacza wartość wielomianu w podanym, jako parametr punkcie. Parametrami funkcji są: n – stopień wielomianu (liczba całkowita), tab – tablica współczynników (współczynniki są liczbami rzeczywistymi) oraz x – punkt (liczba rzeczywista). Funkcja powinna zwracać wyznaczoną wartość wielomianu. Następnie napisz program, który wywoła tą funkcję.
- Dane są dwa wektory liczb rzeczywistych o wymiarze N. Napisz program, który oblicza iloczyn skalarny. Jeśli iloczynu skalarnego nie można obliczyć (np. N<=0), zwróć -1 oraz 1 w przeciwnym razie.
- Dane są dwa wektory liczb rzeczywistych. Napisz program, który oblicza iloczyn wektorowy.
- Dana jest macierz prostokątna o wymiarach NxM. Napisz program, który oblicza indeks elementu maksymalnego, jeśli więcej, to ostatni.
- Dana jest liczba n (n<=9) oznaczająca liczbę cyfr w liczbie całkowitej oraz p (p<=10), podstawa układu liczbowego. Napisz program, który losuje n cyfr zależnych od układu pozycyjnego p i oblicza sumę oraz iloczyn cyfr.
- Napisz program symulujący grę „zgadula”. Gra polega na tym, że komputer „wymyśla” przedział oraz liczbę z tego przedziału. Gracz ma odgadnąć tą liczbę uzyskując informację postaci:
- Moja liczba jest większa,
- Moja liczba jest mniejsza,
- Moja liczba jest równa.
Gra kończy się w momencie odgadnięcia liczby. Wyświetl także liczbę prób gracza.
- Napisz funkcję obliczajacą NWD dwu liczb całkowitych podanych parametrami. Wykorzystaj ją przy obliczeniu NWD elementów tablicy liczb całkowitych dodatnich.
WEJSCIE:
n=4
25
20
150
10
WYJSCIE:
5
- Napisz funkcję obliczającą NWD dwu liczb całkowitych podanych parametrami. Wykorzystaj ją w funkcji skracającej ułamek, którego licznik i mianownik podano jako parametry przekazane przez referencję.
WEJSCIE:
L=25 M=125
WYJSCIE:
L=1 M=5
- Dana jest struktura Student zawierająca imie, nazwisko, średnią. Wykorzystaj ją do utworzenia bazy studentów. Napisz funkcję, która jako wynik zwróci dane studenta o najwyższej średniej.
WEJSCIE:
n=3
Jan Kowal 3.5
Ewa Nowacka 4.5
Ola Nowicka 4.0
WYJSCIE:
Ewa Nowacka 4.5
- Dana jest struktura Student zawierająca imie, nazwisko, tablicę 3 ocen. Wykorzystaj ją do utworzenia bazy studentów. Napisz funkcję, która jako wynik zwróci dane studenta o najwyższej średniej.
WEJSCIE:
n=3
Jan Kowal 5 3.5 4.0
Ewa Nowacka 4.5 4.0 5
Ola Nowicka 4.0 3.0 3.0
WYJSCIE:
Ewa Nowacka 4.5 4.0 5
- Dana jest struktura Student zawierająca imie, nazwisko, średnia. Wykorzystaj ją do utworzenia bazy studentów. Napisz funkcję, która jako wynik zwróci tablicę studentów o średniej powyżej 3.5.
WEJSCIE:
n=3
Jan Kowal 5.0
Ewa Nowik 3.5
Ola Nowicka 4.0
WYJSCIE:
Jan Kowal 5.0
Ola Nowicka 4.0
- Napisz funkcję przeprowadzającą dewaluację stanów kont przechowywanych w strukturze konta zawierającej dane właściciela i stan konta na koniec każdego miesiąca 2015 roku. Dewaluacja ma zostać dokonana począwszy od miesiąca zadanego przez użytkownika. Uwaga: Dewaluacja oznacza przypisanie 10000 stary zł=1 nowy zł). Następnie napisz program, który uruchomi tą funkcję.
- Napisz funkcję, sprawdzającą ile osób ma stan konta na koniec miesiąca większy od x. Stany kont przechowywane są w strukturze zawierającej dane właściciela i stan konta na koniec każdego miesiąca 2015 roku. Zmienna przechowująca liczbę kont spełniających zapytanie, miesiąc i kwota x mają być zadane jako parametry funkcji. Następnie napisz program, który uruchomi tą funkcję.
- Napisz funkcję aktualizującą liczbę studentów o średniej ocen wyższej niż liczba x. Dane studentów przechowywane są w strukturze zawierającej imię i nazwisko i oceny z 5 przedmiotów. Następnie napisz program, który uruchomi tą funkcję.
- Napisz funkcję, aktualizującą adres pracownika. Dane pracowników przechowywane są z użyciem struktury zawierającej imię i nazwisko pracownika, pesel, adres (struktura zawierająca miasto, kod, ulica, numer domu). Pracownik, którego dane mają zostać zmienione wyszukiwany jest za pomocą nazwiska i imienia. W przypadku braku pracownika w bazie powinien zostać wyświetlony odpowiedni komunikat. Następnie napisz program, który uruchomi tą funkcję.
- Napisz funkcję aktualizującą liczbę książek znajdujących się w bibliotece (niewypożyczonych). Baza książek przechowywana jest z użyciem struktury zawierającej: autora, tytuł, ilość egzemplarzy, ilość wypożyczonych egzemplarzy. Zmienna przechowująca liczbę niewypożyczonych książek ma być zadana jako parametr funkcji. Następnie napisz program, w który uruchomi tą funkcję.
- Dana jest tablica jednowymiarowa liczb rzeczywistych i pewien parametr a. Napisz program, który na podstawie tych danych utworzy 3 nowe tablice zawierające odpowiednio: liczby większe od a, mniejsze od a i równe a. Podaj także ich liczebności. Użyj funkcji.
- Napisz funkcję dodającą do każdego elementu wektora (tablicy jednowymiarowej) wartość stałą c, podaną przez użytkownika. Tablica oraz jej rozmiar powinny być przekazane do funkcji za pomocą parametrów. Dodawanie należy zrealizować oddzielnej funkcji. Wynik dodawania w postaci wartości wektora wynikowego ma zostać wyświetlony na ekranie.
- Napisać funkcję wyliczającą N-tą potęgę liczby (liczba i potęga to parametry wejściowe funkcji). Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, która sprawdza, czy zadana, jako parametr liczba całkowita kończy się swoim pierwiastkiem. Liczby kończące się swoim pierwiastkiem to 25, 625. Funkcja powinna zwrócić wartość jeden, jeśli liczba spełnia warunek oraz zero w przeciwnym wypadku.
Napisz program, który wydrukuje na ekranie wszystkie liczby kończące się swoim pierwiastkiem z zakresu 1-10000.
- Napisz funkcję, która posiada trzy parametry formalne. Pierwszym parametrem jest liczba a, drugim tablica liczb tab zaś trzecim – liczba n. Funkcja ma dla zadanej liczy a zwracać w tablicy tab jej kod binarny. Liczba n ma informować o tym ile elementów tablicy zostało wypełnionych. Następnie napisz program, który wywoła tą funkcję.
- Napisz funkcję, do której przekazywany jest N – elementowy wektor liczb całkowitych oraz liczba całkowita x. Funkcja powinna obliczyć i zwrócić ilość wystąpień liczby x w wektorze.
- Napisz funkcję, do której przekazywana jest N× M – elementowa tablica dwuwymiarowa liczb całkowitych oraz tablica jednowymiarowa. Funkcja powinna odnaleźć najmniejszą liczbę nieparzystą w poszczególnych wierszach tablicy dwuwymiarowej a następnie zwrócić je w postaci tablicy jednowymiarowej.
- Napisz funkcję, która policzy pole i obwód prostokąta, kwadratu, trójkąta( dla każdej figury oddzielna funkcja). Wybór figury powinien odbywać się za pomocą instrukcji switch.
- Dana jest tablica liczb rzeczywistych o N wierszach i 3 kolumnach. Pierwsza i druga kolumna zawierają, odpowiednio, współrzędne x i y punktów znajdujących się w prostokątnym układzie współrzędnych. Napisz program, który dla każdego punktu zapisze w trzeciej kolumnie jego odległość od początku układu współrzędnych. Do obliczenia odległości punktu od początku układu współrzędnych zastosuj dodatkową funkcję. Odległość punktu (x, y) od początku układu współrzędnych określona jest wzorem:
10.6.Zadania ze „ Wstępu do programowania”
Zalecenia dydaktyczne: w rozwiązaniach korzystamy z funkcji dla odpowiednich działań (dobór tych działań jest elementem oceny). Komunikacja: zmienne przekazywane przez wartość i referencję.
- Napisz funkcję, która na podstawie dwu całkowitych parametrów obliczy liczbę wszystkich liczb parzystych, nieparzystych i podzielnych przez 3 znajdujących się między nimi. Wypisz te wartości za pomocą innej funkcji.
WEJŚCIE:
10
20
WYJŚCIE:
Liczba liczb parzystych: 6
Liczba liczb nieparzystych: 5
Liczba liczb podzielnych przez 3: 3
- Napisz funkcję, która na podstawie trzy argumentów typu całkowitego sprawdzi czy podane liczby są liczbami pitagorejskimi (funkcja ma zwrócić 1 gdy odpowiedź jest twierdząca, 0 w przeciwnym wypadku). Wynik wyświetl za pomocą innej funkcji.
WEJSCIE:
5
13
12
WYJŚCIE:
Liczby 5, 13, 12 są liczbami pitagorejskimi
WEJŚCIE:
5
10
11
WYJŚCIE:
Liczby 5, 10, 11 nie są liczbami pitagorejskimi
-
- Napisz program, który uzupełni losowymi wartościami tablice N-elementową liczb rzeczywistych, wyświetli ją na monitorze komputera, a następnie policzy medianę. W rozwiązaniu użyj funkcji.
WEJŚCIE:
5
{ 13.3 15.7 8.0 2.0 19.0}
WYJŚCIE:
Mediana: 13.3
- Dana jest n-elementowy wektor losowych liczb rzeczywistych. Napisz program, który posortuje ten wektor jedną z metod do wyboru: S – przez selekcję lub W – przez wstawianie. Sortowanie powinno odbywać się: -1 – malejąco lub 1 – rosnąco. Nagłówek funkcji sort( int n, float tab, int kierunek, char algorytm);
WEJŚCIE:
{ 13.3 15.7 8.0 2.0 19.0}
W
-1
WYJŚCIE:
Wektor posortowany malejąco metodą „przez wstawianie”: [2.0 8.0 13.3 15.7 19.0]
- Dane są dwa wektory N-elementowe A i B liczb całkowitych losowych. Napisz program, który obliczy następujące wektory: A+B, A-B, A*BT (T oznacza transponowanie). Każda operacja na wektorach jest realizowane przez odpowiednie funkcje.
WEJŚCIE:
4
{2 4 -1 4}
{3 1 3 5}
WYJŚCIE:
A+B: {5 5 2 9}
A-B: {-1 3 -4 -1}
A*Bt: 27
- Dana jest macierz NxM (N,M>1) liczb losowych całkowitych z przedziału <-5, 10>. Napisz funkcję wyznaczającą wartość maksymalna i minimalną. Wypisz obliczone wartości.
WEJŚCIE:
2
3
{ {5 -2 9}
{2 -1 3} }
WYJŚCIE:
Minimum: -2
Maksimum: 9
- Dana jest macierz NxM (N,M>2) liczb losowych całkowitych z przedziału <-20, 20>. Napisz program, który obliczy sumę elementów zewnętrznych dodatnich i sumę elementów wewnętrznych ujemnych. Wypisz je.
WEJŚCIE:
3
3
{ {5 -2 9}
{-4 -17 5}
{2 -1 3} }
WYJŚCIE:
Suma elementów zewnętrznych dodatnich: 24
Suma elementów wewnętrznych ujemnych: -17
- Napisz funkcję, która dla określonej parametrem liczby całkowitej zwróci wartość liczby czytanej wspak. Wykorzystaj ją do wypisania wyników dla n liczb.
WEJSCIE:
n=3
1234
576
332
WYJSCIE:
4321
65
233