INF1 2011 Prac 07

background image

Informatyka 1 - Pracownia

Strona 1 z 9

© 2011 Jarosław Forenc

MATERIAŁY POMOCNICZE NR 7

DO PRACOWNII Z PRZEMIOTU „INFORMATYKA 1”

Funkcje



W programie w języku C zawsze występuje co najmniej jedna funkcja - main().



Od funkcji main() rozpoczyna się wykonanie całego programu.



Oprócz niej mogą występować także inne funkcje zdefiniowane przez użytkownika.



Ogólna struktura funkcji w języku C jest następująca:

float add(float a, float b)

{

float y;

y = a + b;

return y;

}

argumenty

przekazywane do funkcji

nazwa funkcji

typ wartości

zwracanej

przez funkcję

instrukcja

nagłówek funkcji

ciało funkcji

wartość zwracana

przez funkcję

instrukcja
instrukcja


Przykład nr 8.1

Funkcja dodająca dwie liczby.

#include <stdio.h>
#include <conio.h>

float add(float a, float b)
{
float y;
y = a + b;
return y;
}

int main()
{
float x1=10.0, x2=20.0, wynik;

wynik = add(x1,x2);
printf("Wynik = %f\n", wynik);

getch()
return 0;
}



Wykonanie powyższego programu rozpoczyna się od funkcji main().

Informatyka 1 - Pracownia

Strona 2 z 9

© 2011 Jarosław Forenc



Gdy dochodzimy do instrukcji zawierającej funkcję add(), to wywołanie tej funkcji
powoduje przekazanie sterowania do jej pierwszej instrukcji.



Do funkcji add() przekazywane są dwa parametry typu float. Pierwszy parametr (a)
otrzymuje wartość pierwszego parametru wywołania funkcji (x1), natomiast drugi
parametr (b) - wartość drugiego parametru wywołania funkcji (x2).



Powrót z funkcji (do miejsca zaraz po jej wywołaniu) następuje na skutek wykonania
instrukcji return.



Wartość zwracana przez funkcję podstawiana jest pod zmienną wynik.



Po słowie return może występować dowolne wyrażenie. Wyrażenie to często
umieszczane jest w nawiasach, ale nie jest to konieczne.



Funkcję add() można zapisać w prostszy sposób:

float add(float a, float b)
{
return (a+b);
}



W wywołaniu funkcji jako parametry mogą występować zmienne, wyrażenia
arytmetyczne lub stałe liczbowe, np.

wynik = add(10,20);
wynik = add(x1*20+4,x1/x2);



Istnieją funkcje, które nie zwracają żadnej wartości, wtedy jako typ zwracanego wyniku
podajemy void, np.

void drukuj(int a)
{
printf(“Liczba a wynosi: %d \n”,a);
return;
}



Wywołanie takiej funkcji w programie ma postać:

drukuj(-10);



Powyższa funkcja nie zwraca żadnego wyniku więc wystarczy samo słowo return. Jeśli
funkcja nie zwraca wyniku i nie ma w jej ciele return to sterowanie wraca do punktu
wywołania na skutek zakończenia wykonania wszystkich instrukcji w bloku funkcyjnym.



Mogą istnieć funkcje, do których nie przekazujemy żadnych parametrów formalnych, np.

void linia()
{
printf(”----------\n”);

lub

}

void linia(void)
{
printf(”----------\n”);
}



Wywołanie takich funkcji w programie ma postać:

linia();

- nawiasy są konieczne.



Ale już zapis:

linia(void)
{
printf(”----------\n”);
}

background image

Informatyka 1 - Pracownia

Strona 3 z 9

© 2011 Jarosław Forenc

nie jest równoważny powyższym zapisom, gdyż jeśli nie podamy typu zwracanej
wartości przez funkcję, to domyślnie jest to typ int.


Umieszczanie definicji funkcji w programie



Definicje funkcji można umieszczać w dowolnym miejscu programu - przed lub po
funkcji main(). Należy jednak pamiętać o tym, że zasięg widzialności funkcji rozpoczyna
się od miejsca jej deklaracji.



Jeśli chcemy umieścić definicję funkcji po funkcji main(), czyli po miejscu, w którym
jest wywoływana, to musimy wcześniej podać jej formalną deklarację czyli prototyp.



Prototyp opisuje to samo co nagłówek, ale kończy się średnikiem. W prototypie nie
musimy podawać nazw argumentów formalnych - wystarczą tylko typy.



Podanie nazw argumentów ma jednak znaczenie dla czytelności programu.



Dzięki prototypom kompilator ma możliwość sprawdzenia zgodności typów formalnych
i faktycznych.



Rozpatrzmy strukturę następujących dwóch programów:

#include …

void fun(int a, int b);

int main()
{

fun(a,b);

}

void fun (int a, int b)
{

}

#include …

void fun (int a, int b)
{

}

int main()
{

fun(a,b);

}



W programie po lewej stronie funkcja fun() zdefiniowana jest po funkcji main(), dlatego
przed funkcją main() umieszczony jest prototyp funkcji fun(), który może mieć jedną
z dwu postaci:

void fun(int a, int b);

lub

void fun(int, int);



W programie po prawej stronie umieszczenie prototypu funkcji fun() nie jest konieczne,
gdyż definicja funkcji fun() umieszczona jest przed funkcją main().


Przekazywanie parametrów do funkcji przez wartość



Przekazywanie parametrów przez wartość oznacza, że po przekazaniu sterowania do
funkcji tworzone są kopie zmiennych przekazywanych do funkcji i wszystkie działania
w funkcji wykonywane są na kopiach.

Informatyka 1 - Pracownia

Strona 4 z 9

© 2011 Jarosław Forenc

Przykład nr 8.2

Przekazywanie parametrów do funkcji przez wartość.

#include <stdio.h>
#include <conio.h>

void fun(

int a

,

int b

)

{
printf("fun1: a=%3d, b=%3d \n",

a

,

b

);

a

= 10;

b

= 10;

printf("fun2: a=%3d, b=%3d \n",

a

,

b

);

}

int main()
{
int

a

= 20,

b

= 20;


printf("main1: a = %3d, b = %3d \n",

a

,

b

);

fun(

a

,

b

);

printf("main2: a = %3d, b = %3d \n",

a

,

b

);


getch();
return 0;
}



Wynik działania programu:

main1: a = 20, b = 20
fun1: a = 20, b = 20
fun2: a = 10, b = 10
main2: a =

20

, b =

20



Po powrocie z funkcji fun() wartości zmiennych a i b nie zmieniły się, gdyż w funkcji
fun() pracowaliśmy na ich kopiach (posiadających takie same nazwy).


Przekazywanie parametrów do funkcji przez wskaźnik



Przekazywanie parametrów do funkcji przez wskaźnik polega na tym, że do funkcji
przekazywane są adresy zmiennych. Wszystkie operacje w funkcji wykonywane są zatem
na zmiennych z funkcji wywołującej (poprzez adres tych zmiennych).

Przykład nr 8.3

Przekazywanie parametrów do funkcji przez wskaźnik.

#include <stdio.h>
#include <conio.h>

void fun(

int *a

,

int *b

)

{
printf("fun1: a=%3d, b=%3d \n",

*a

,

*b

);

*a

= 10;

*b

= 10;

background image

Informatyka 1 - Pracownia

Strona 5 z 9

© 2011 Jarosław Forenc


printf("fun2: a=%3d, b=%3d \n",

*a

,

*b

);

}

int main()
{
int

a

= 20,

b

= 20;


printf("main1: a = %3d, b = %3d \n",

a

,

b

);

fun(

&a

,

&b

);

printf("main2: a = %3d, b = %3d \n",

a

,

b

);


getch();
return 0;
}



Wynik działania programu:

main1: a = 20, b = 20
fun1: a = 20, b = 20
fun2: a = 10, b = 10
main2: a =

10

, b =

10



Po powrocie z funkcji fun() wartości zmiennych a i b zostały zmienione, gdyż do funkcji
fun() przekazane zostały adresy zmiennych a i b (&a, &b) i pracowaliśmy na zmiennych
poprzez ich adresy.



W funkcji main():

int a

;

- deklaracja zmiennej typu int,

a

- zmienna typu int,

&a

- adres zmiennej, a nie jej wartość.



W funkcji fun():

int *a;

- deklaracja zmiennej wskaźnikowej (wskaźnik na int),

a

- adres zmiennej typu int,

*a

- wartość zmiennej wskazywanej przez a.



Zmienne lokalne i zmienne globalne



Zmienne zadeklarowane w funkcjach są zmiennymi lokalnymi widzianymi tylko
w obrębie danej funkcji (bloku funkcyjnego) od miejsca, w którym zostały
zadeklarowane. Zmienne lokalne są zmiennymi automatycznymi.



Zmienne zadeklarowane poza funkcją main są zmiennymi globalnymi widzianymi
w całym programie od miejsca deklaracji (są to zmienne statyczne).



Jeśli zmienna globalna i lokalna mają takie same nazwy, to zmienna lokalna przesłania
widzialność zmiennej globalnej w danej funkcji.

Informatyka 1 - Pracownia

Strona 6 z 9

© 2011 Jarosław Forenc

#include ...

int a, b;

void f1()
{
float a, c;
...
}

int main()
{
int c, d;
...
}



zmienne a i b typu int są zmiennymi globalnymi,



zmienne a i c typu float są zmiennymi lokalnymi widzianymi
tylko w funkcji f1(),



zmienne c i d typu int są zmiennymi lokalnymi widzianymi
tylko w funkcji main(),



zmienna globalna b widziana jest w obu funkcjach: f1()
i main(),



zmienna globalna a widziana jest tylko w funkcji main(),
gdyż w funkcji f1() jej nazwa została przesłonięta przez
zmienną lokalną a typu float.



Przekazywanie tablicy jednowymiarowej (wektora) do funkcji



Przy przekazywaniu do funkcji wektora, w nagłówku funkcji umieszczamy typ
elementów wektora, jego nazwę i same nawiasy kwadratowe lub nawiasy kwadratowe
z rozmiarem wektora:

void zeruj(int tab[])

lub

void zeruj(int tab[5])



W wywołaniu funkcji podajemy natomiast tylko nazwę wektora:

zeruj(tab);

Przykład nr 8.4

Przekazywanie do funkcji tablicy jednowymiarowej (wektora).

#include <stdio.h>
#include <conio.h>

void zeruj(

int tab[5]

)

{
int i;
for(i=0; i<5; i++) tab[i] = 0;
}

int main()
{
int i, tab[5] = {1,2,3,4,5};

for(i=0; i<5; i++) printf("%3d",tab[i]);
printf("\n");

zeruj(tab);

for(i=0; i<5; i++) printf("%3d",tab[i]);
printf("\n");

getch();
return 0;
}

background image

Informatyka 1 - Pracownia

Strona 7 z 9

© 2011 Jarosław Forenc



Wynikiem działania powyższego programu jest:

1 2 3 4 5
0 0 0 0 0



Do funkcji zeruj() jest przekazywany adres wektora. Wszystkie operacje dokonane na
wektorze w funkcji są uwzględnione po wyjściu z niej.



Przekazywanie tablicy dwuwymiarowej (macierzy) do funkcji



Przy przekazywaniu do funkcji tablicy dwuwymiarowej musimy koniecznie podać liczbę
wierszy i kolumn lub tylko liczbę kolumn:

void zeruj(int tab[2][3])

lub

void zeruj(int tab[][3])



W wywołaniu funkcji podajemy natomiast tylko nazwę tablicy:

zeruj(tab);

Przykład nr 8.5

Przekazywanie do funkcji tablicy dwuwymiarowej (macierzy).

#include <stdio.h>
#include <conio.h>

void zeruj(

int tab[][3]

)

{
int i, j;
for(i=0; i<2; i++)
for(j=0; j<3; j++)
tab[i][j] = 0;
}

void drukuj(

int tab[2][3]

)

{
int i, j;
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
printf("%3d",tab[i][j]);
printf("\n");
}
printf("\n");
}

int main()
{
int i, j, tab[2][3] = {{1,2,3},{4,5,6}};

drukuj(tab);

zeruj(tab);

drukuj(tab);

getch();
return 0;
}

Informatyka 1 - Pracownia

Strona 8 z 9

© 2011 Jarosław Forenc



Wynikiem działania powyższego programu jest:

1 2 3
4 5 6

0 0 0
0 0 0



Do funkcji zeruj() jest przekazywany adres macierzy. Wszystkie operacje dokonane na
macierzy w funkcji są uwzględnione po wyjściu z niej.



Przekazywanie struktur do funkcji



Struktury przekazywane są do funkcji tak jak każde inne zmienne podstawowych typów,
czyli przez wartość.

Przykład nr 8.6

Program zawierający funkcję obliczającą odległość dwóch punktów.

#include <stdio.h>
#include <conio.h>
#include <math.h>

struct punkt
{
int x, y;
};

float odleglosc(struct punkt pkt1, struct punkt pkt2)
{
return sqrt(pow(pkt2.x-pkt1.x,2)+pow(pkt2.y-pkt1.y,2));
}

int main()
{
struct punkt p1 = {2,3}, p2 = {-2,1};
float odl;

odl = odleglosc(p1,p2);
printf("Punkt nr 1: (%d,%d)\n",p1.x,p1.y);
printf("Punkt nr 2: (%d,%d)\n",p2.x,p2.y);
printf("Odleglosc = %g\n",odl);

getch();
return 0;
}


Rekurencyjne wywołanie funkcji



Rekurencyjne wywołanie funkcji polega na ponownym jej wywołaniu zanim skończyło
się jej poprzednie wywołanie.



Poniżej znajdują się trzy wersje funkcji obliczającej silnię liczby n.

background image

Informatyka 1 - Pracownia

Strona 9 z 9

© 2011 Jarosław Forenc

Przykład nr 8.7 (a)

Funkcja obliczająca silnię liczby (wersja nierekurencyjna).

int silnia(int n)
{
int i, wynik = 1;

for (i=1; i<=n; i++)
wynik = wynik * i;
return wynik;
}

Przykład nr 8.7 (b)

Funkcja obliczająca silnię liczby (wersja rekurencyjna).

int silnia(int n)
{
if (n<=1)
return 1;
else
return n*silnia(n-1);
}

Przykład nr 8.7 (c)

Funkcja obliczająca silnię liczby (wersja rekurencyjna).

int silnia(int n)
{
return n ? n*silnia(n-1) : 1;
}


Wyszukiwarka

Podobne podstrony:
INF1 2011 Wykl 07 Dzienne 4na1
INF1 2011 Wykl 07 Dzienne 4na1
2011 10 07
2011.10.07 - (W1b) Fizjologia nerki, Fizjologia człowieka, wykłady
SIMR-ALG1-EGZ-2011-02-07-rozw
egzamin zawodowy 2011 prac biurowych
2011 02 07 Życzę Ci pps mcid 27255 ppt
2011 12 07 Buprenorphine Actavis SPC finalid 27543
WYTYCZNE DO PISANIA PRAC 07 09 2009, rynek transportu i logistyki w Polsce, Logistyka WSB Chorzów
2011 04 07
2011 06 07 wyklad, leki z antybiotykami
2011-01-07, Warsztatowcy znow na Chalubinskiego (1)
TEST 2011 05 07 01
Prawo cywilne ćw.9 2011-03-07, Prawo Cywilne
2011 01 07 WIL Wyklad 14id 2751 Nieznany (2)
Obywatelstwo definitywnie utracone Nasz Dziennik, 2011 03 07
2011 03 07 Seks maszyna na uniwersytecie
Santo subito Mój ulubiony święty Nasz Dziennik, 2011 03 07

więcej podobnych podstron