background image

C/C++

funkcje

postać, przekazywanie parametrów
argumenty funkcji main() 
funkcje rekurencyjne
funkcje przeci
ąŜone

zasięg deklaracji zmiennych
przesłanianie zmiennych

background image

C/C++ - funkcje

Funkcje są jedynymi  elementami strukturalnymi w języku C i podstawowym 
budulcem klas w C++. 

Funkcje są podprogramami które separują pewien fragment kodu od pozostałej 
części programu.

Posiadają identyfikator (nazwę), oraz jest dla nich określany sposób 
przekazywania parametrów (argumentów) i zwracania rezultatów działania, 
czyli interfejs.

Raz napisana funkcja moŜe być wielokrotnie wykorzystana poprzez 
wywołanie z parametrami aktualnymi (wywołania).

funkcja

parametry

rezultat

background image

C/C++ - funkcje 

Ogólna postać funkcji jest następująca:

typ_rezultatu nazwa_funkcji(lista_parametrów)
{

ciało funkcjiczyli instrukcje
return wynik;

}

W pierwszym wierszu definicji funkcji następuje określenie typu rezultatu 
zwracanego przez funkcję, nazwy funkcji oraz określenie argumentów (parametrów) 
stanowiących dane wymagane przez funkcję do prawidłowego wyznaczenia rezultatu 
działania funkcji. Instrukcje wykonywane w ramach funkcji są ujęte w nawiasy 
programowe. Wynik działania funkcja zwraca wykonując instrukcję return
Instrukcja return kończy działanie funkcji. Wartość zwracana poleceniem  return
musi być zgodna z typem rezultatu określonym w pierwszym wierszu definicji 
funkcji. Pominięcie określenia typu rezultatu zwracanego przez funkcję oznacza 
przyjęcie domyślnego typu int.  Lista parametrów zawiera listę deklaracji zmiennych 
(tzw. parametrów formalnych funkcji). Poszczególne jej elementy są separowane 
przecinkiem. 

background image

C/C++ - funkcje

Przykład . Funkcja na obliczanie silni liczby.

long int silnia(int liczba)

{

long int silnia=1;

for(int i=2;i<=liczba;i++) silnia*=i;

return silnia;   //zwrócenie wyniku przez funkcj

ę

main()

{

int n;

long int r;

r=silnia(n); // wywołanie funkcji

return 0;

}

parametr 

formalny

parametr aktualny

przykład

W momencie wywołania funkcji parametry aktualne „kojarzone” są z
parametrami formalnymi.

background image

C/C++ - funkcje

Przekazywanie parametrów do funkcji 

Poprawnie zdefiniowana funkcja nie korzysta ze zmiennych globalnych 

(zadeklarowanych poza  funkcjami).

Wszystkie potrzebne dane funkcja powinna otrzymywać przez listę parametrów. 

WyróŜnia się trzy sposoby przekazywania parametrów do funkcji:

1.

przez wartość

2.

przez adres (wskaźnik)

3.

przez referencję

Przekazywanie parametrów przez wartość umoŜliwia jedynie przekazanie wartości 

zmiennych, funkcja w tym przypadku nie moŜe  modyfikować wartości 
zmiennych przekazywanych jako parametry.

Aby funkcja mogła zmieniać zawartość zmiennej musi otrzymać jej adres  lub 

zmienna musi być  przekazana przez referencję.

background image

C/C++ - funkcje

Przekazywanie parametrów przez wartość

przykład

float suma(float a,float b)  

{

a=a+b;

return a;

}

main()

{

float x=3.4,y=4.6,z;

z=suma(x,y);// po wywołaniu funkcji warto

ść

 zmiennej 

//nie uległa zmianie i wynosi nadal x=3.4

return 0;

background image

C/C++ - funkcje

Przekazywanie parametrów przez adres (zmienną wskaźnikową)

przykład

void suma(float *a,float b)  //wynik zwracany przez 

// pierwszy składnik

{

*a=*a+b;   

}

main()

{

float x=2.4,y=4.7;

suma(&x,y);

// w wywołaniu funkcji przekazywany jest 

//adres zmiennej w której znajdzie si

ę

 wynik

return 0; 

background image

C/C++ - funkcje

Zmienne referencyjne

W języku C++ został wprowadzony tzw. typ referencyjny  umoŜliwiający 
kojarzenie zmiennych ze zmiennymi referencyjnymi w takim sensie, Ŝe 
operacja na zmiennej referencyjnej powoduje natychmiastową modyfikację 
zmiennej  z nią skojarzonej i nadanie jej takiej samej wartości.

W linii deklaracji zmiennej referencyjnej naleŜy skojarzyć z nią zmienna.

Deklaracja zmiennej referencyjnej:

int x, &r=x;  // r zmienna referencyjna

r=20;

cout<<x;

przykład

background image

C/C++ - funkcje

Przekazywanie parametrów przez referencję

przykład

void suma(float &a,float b)  //wynik zwracany przez 

// pierwszy składnik

{

a=a+b;   

}

main()

{

float x=2.4,y=4.7;

suma(x,y);

// wynik w zmiennej x

return 0;

background image

C/C++ - funkcje

Przekazywanie tablic do funkcji -

tablice jednowymiarowe

W przypadku przekazywania funkcjom tablic jednowymiarowych (takŜe 

wielowymiarowych) nie jest moŜliwe przekazanie tablicy przez wartość. 
Podczas wywołania funkcji naleŜy przekazać adres pierwszego  elementu 
tablicy (wskaźnik do początku tablicy). 

Parametr formalny (w definicji funkcji) moŜna zadeklarować  jako: 

wskaźnik,
tablicę o określonym rozmiarze,
tablicę o nieokreślonym rozmiarze.

W kaŜdym z przypadków informację o długości tablicy naleŜy przekazać 
niezaleŜnie. 
W funkcji do elementów tablicy odwoływać się moŜna dwojako:  przez 
wskaźnik lub przez operator []. 

background image

C/C++ - funkcje

Przekazywanie tablic jednowymiarowych do funkcji przez wskaźnik do typu 

elementu 

(odwoływanie do elementu przez wskaźnik)

przykład

#include <conio.h>

#include <iostream>

#define N 5

double srednia(int *w,int n)

{

double wynik;

for (int i=0;i<n;i++) wynik+=*(w+i);

return wynik/n;

}

main ()

{

int wek[N]={1,2,3,4,5};

double x;

x=srednia(wek,N);

cout<<"srednia elementów: "<<x;

getch();

return(0);

background image

C/C++ - funkcje

Przekazywanie tablic jednowymiarowych do funkcji przez wskaźnik

do typu elementu (odwoływanie do elementu przez operator [])

przykład

#include <conio.h>

#include <iostream>

#define N 5

double srednia(int *w,int n)

{

double wynik;

for (int i=0;i<n;i++) wynik+=w[i];

return wynik/n;

}

main ()

{

int wek[N]={1,2,3,4,5};

double x;

x=srednia(wek,N);

cout<<"srednia elementów: "<<x;

getch();

return(0);

background image

C/C++ - funkcje

Przekazywanie tablic jednowymiarowych do funkcji przez deklarację 

wskaźnika do tablicy  (określony rozmiar) 

przykład

#include <conio.h>

#include <iostream>

#define N 5

double srednia(int w[5],int n)

{

double wynik;

for (int i=0;i<n;i++) wynik+=w[i];

return wynik/n;

}

main ()

{

int wek[N]={1,2,3,4,5};

double x;

x=srednia(wek,N);

cout<<"srednia elementów: "<<x;

getch();

return(0);

background image

C/C++ - funkcje

Przekazywanie tablic jednowymiarowych do funkcji przez deklarację 

wskaźnika do tablicy  ( nieokreślony rozmiar)

przykład

#include <conio.h>

#include <iostream>

#define N 5

double srednia(int w[],int n)

{

double wynik;

for (int i=0;i<n;i++) wynik+=w[i];

return wynik/n;

}

main ()

{

int wek[N]={1,2,3,4,5};

double x;

x=srednia(wek,N);

cout<<"srednia elementów: "<<x;

getch();

return(0);

}

background image

C/C++ - funkcje

Przekazywanie tablic jednowymiarowych do funkcji przez deklarację 

wskaźnika do tablicy  (nieokreślony rozmiar) odwołanie przez wskaźnik

przykład

#include <conio.h>

#include <iostream>

#define N 5

double srednia(int w[],int n)

{

double wynik;

for (int i=0;i<n;i++) wynik+=*(w+i);

return wynik/n;

}

main ()

{

int wek[N]={1,2,3,4,5};

double x;

x=srednia(wek,N);

cout<<"srednia elementów: "<<x;

getch();

return(0);

}

background image

C/C++ - funkcje

Przekazywanie tablic do funkcji -

tablice wielowymiarowe

W przypadku przekazywania tablic wielowymiarowych jeŜeli 

parametr formalny został zadeklarowany jako wskaźnik, to w 
funkcji do elementów tablicy odwoływać się moŜna jedynie przez 
wskaźnik (odpowiednio obliczając adres w oparciu o indeksy 
tablicy.

JeŜeli natomiast, jako parametr formalny zadeklarowana została 

tablica to musi ona posiadać określone wszystkie wymiary poza 
ostatnim (określonym tuŜ za nazwą tablicy). MoŜna oczywiście 
podać wszystkie wymiary. Podanie wymaganych wymiarów jest 
konieczne aby w funkcji moŜna było odwoływać się do 
elementów przez indeksy (przez []).

background image

C/C++ - funkcje

Przekazywanie tablic do funkcji -

tablice wielowymiarowe

W wywołaniu funkcji  jako parametr aktualny podać naleŜy:

-

adres pierwszego elementu np. &TAB[0][0], jeśli w liście 
parametrów formalnych zadeklarowany został wskaźnik,

-

nazwę tablicy np. TAB, jeśli w liście parametrów formalnych 
zadeklarowana została tablica. Wynika to z faktu, Ŝe &TAB[0][0] 
jest adresem pierwszego elementu tablicy, a TAB jest wskaźnikiem
do tablicy (zawiera informację o wymiarach), co przy tablicy o 
wymiarach 2x3 moŜna zapisać:

int (*wsk)[2][3]  .

background image

C/C++ - funkcje

Przekazywanie tablicy dwuwymiarowej do funkcji przez wskaźnik do typu 

elementu tablicy

przykład

#include <conio.h>

#include <iostream>

#define N 2 

#define M 3

double srednia(int *w,int n,int m)

{

double wynik;

for (int i=0;i<n;i++)

for (int j=0;j<m;j++) wynik+=*(w+i*m+j);

return wynik/(n*m);

}

main ()

{

int tab[N][M]={1,2,3,4,5,6};

double x;

x=srednia(&tab[0][0],N,M); // x=srednia(tab,N,M); - bł

ą

d

cout<<"srednia elementów: "<<x;

getch();

return(0);

}

background image

C/C++ - funkcje

Przekazywanie tablicy dwuwymiarowej do funkcji przez deklarację 

wskaźnika do tablicy  

przykład

#include <conio.h>

#include <iostream>

#define N 2 

#define M 3

double srednia(int w[][M],int n,int m)

{

double wynik;

for (int i=0;i<n;i++)

for (int j=0;j<m;j++) wynik+=w[i][j];

return wynik/(n*m);

}

main ()

{

int tab[N][M]={1,2,3,4,5,6};

double x;

x=srednia(tab,N,M);    // x=srednia(&tab[0][0],N,M); - bł

ą

d

cout<<"srednia elementów: "<<x;

getch();

return(0);

}

background image

C/C++ - funkcje

Przekazywanie struktur do  funkcji 

Struktury do funkcji  przekazuje się jak zmienne typu prostego, czyli przez:  wartość, 

wskaźnik, referencję.

Przykład. Przekazywanie struktury przez wartość.

przykład

#

include <iostream>

#include <math.h>

struct zespolona {

double re, im;

};

double modul(zespolona x)

{

return sqrt((x.re)*(x.re++)+(x.im)*(x.im));

//             x.re zwiekszono o 1       

}

int main()

{

zespolona zz={3.0,4.0};  // zainicjowanie zmiennej zespolonej

double y=modul(zz);

cout<<"abs("<<zz.re<<"+j"<<zz.im<<")="<<y;

// zz.re nie ulegla zmianie

return 0

}

background image

C/C++ - funkcje

Przekazywanie struktur do  funkcji 

Przykład. Przekazywanie struktury przez wskaźnik.

przykład

#

include <iostream>

#include <math.h>

struct zespolona {

double re, im;

};

double modul(zespolona *x)

{

return sqrt((x->re)*(x->re++)+(x->im)*(x->im));

//             x->re zwiekszono o 1       

}

int main()

{

zespolona zz={3.0,4.0};  // zainicjowanie zmiennej zespolonej

double y=modul(zz);

cout<<"abs("<<zz.re<<"+j"<<zz.im<<")="<<y;

// zz.re została zmodyfikowana

return 0

}

background image

C/C++ - funkcje

Przekazywanie struktur do  funkcji 

Przykład. Przekazywanie struktury przez referencję.

przykład

#

include <iostream>

#include <math.h>

struct zespolona {

double re, im;

};

double modul(zespolona &x)

{

return sqrt((x.re)*(x.re++)+(x.im)*(x.im));

//             x->re zwiekszono o 1       

}

int main()

{

zespolona zz={3.0,4.0};  // zainicjowanie zmiennej zespolonej

double y=modul(zz);

cout<<"abs("<<zz.re<<"+j"<<zz.im<<")="<<y;

// zz.re została zmodyfikowana

return 0

}

background image

C/C++ - funkcje

Przekazywanie argumentów   funkcji  main()

W języku C/C++ moŜliwe jest przekazywanie parametrów 

aplikacji . W tym celu naleŜy w liście argumentów funkcji 
main() umieścić dwa elementy. Pierwszy przekazuje liczbę 
argumentów a drugi wskaźnik do tablicy łańcuchów którymi 
są poszczególne parametry. Pierwszym argumentem 
obligatoryjnie staje się nazwa programu.

Argumenty  aplikacji (z wiersza poleceń) zadaje się po nazwie 

programu separując spacjami. 

background image

#

include <iostream>

#include <conio.h>

int main(int argc, char *argv[])

{int a,b;

cout<< argc<<'\n';

for (int i=0;argv[i];i++)

cout<< argv[i]<<'\n';

//  a=argv[1];     // bł

ą

d

a=atoi(argv[1]);// atoi() – konwersja ła

ń

cucha na liczb

ę

int

cout<<a+1<<'\n';

getch();

return 0;

}

przykład

C/C++ - funkcje

Przekazywanie argumentów   funkcji main()

background image

C/C++ - funkcje

Funkcje rekurencyjne

Funkcje rekurencyjne są funkcjami, które w swoim ciele wywołują samą siebie.
NaleŜy wiedzieć, iŜ przy wywołaniu funkcji rekurencyjnej dochodzi do jej wielokrotnego 

wywołania bez kończenia wywołań poprzednich. Idzie za tym konieczność 
wielokrotnego składowania parametrów na stosie, co moŜe prowadzić do jego 
przepełnienia.

Zaletą funkcji rekurencyjnych jest duŜa szybkość wykonywania.

Ogólna postać funkcji rekurencyjnej

int funkcja_rek (int parametr)

{

...

liczba=funkcja_rek(parametr);

...  

return 0;

background image

C/C++ - funkcje

Funkcje rekurencyjne 

Przykład. Iteracyjna i rekurencyjna postać funkcji na obliczanie silni

przykład

long double SilniaIteracyjna(int liczba)

{

long double silnia=1;

for(int i=1; i<=liczba; i++)

silnia*=i;

return silnia;

}

long double SilniaRekurencyjna(int liczba)

{

if (liczba==0)

return 1;

else 

return liczba*SilniaRekurencyjna(liczba-1);

}

background image

C/C++ - funkcje

Funkcje przeciąŜone 

W języku C++ istnieje moŜliwość deklarowania funkcji o tej 

samej nazwie i róŜnych interfejsach, czyli róŜnej liczbie 
argumentów, róŜnych ich typach, odmiennym sposobie 
zwracania wyników. Funkcje takie noszą nazwę 
przeciąŜonych lub przeładowanych.

Oczywiście funkcje przeciąŜone będą róŜniły się takŜe ciałami.

W przypadku funkcji przeciąŜonych kompilator rozpoznaje 

funkcję po nazwie, liście argumentów i typie rezultatu.

background image

C/C++ - funkcje

Funkcje przeciąŜone 

Przykład. Funkcja przeciąŜona na obliczanie modułu liczby: całkowitej, 

rzeczywistej i zespolonej.

przykład

struct complex{

double re,im;

};

double abs(double x)

{

return x>0?x:-x;

}

int abs(int i)

{

return i>0?i:-i;

}

double abs(complex z)

{

return sqrt(z.re*z.re+z.im*z.im);

}

int main(){

complex s={-2,4};

cout<<abs(-12.39)<<"\n";

cout<<abs(35)<<"\n";

cout<<abs(s)<<"\n";

getch();

return 0;

}

background image

C/C++ - zasięg deklaracji zmiennych

1.

W języku C/C++ nie ma obowiązku deklarowania zmiennych w określonym 
miejscu. Pamiętać jednak, Ŝe od miejsca deklaracji zmiennej zaleŜy jej zasięg.

2.

Zmienne globalne (deklarowane poza funkcjami) posiadają domyślną klasę 
pamięci static i są widoczne w kaŜdym miejscu w programie o ile nie zostały 
przesłonięte przez zmienne lokalne funkcji. Zmienne lokalne (deklarowane w 
funkcjach) są widoczne widoczne tylko wewnątrz funkcji w których zostały 
zadeklarowane.

3.

Zmienne zadeklarowane wewnątrz funkcji posiadają domyślną klasę auto i są 
usuwane z pamięci po zakończeniu działania funkcji. Deklaracja zmiennej klasy 
static wewnątrz funkcji powoduje, Ŝe pozostaje ona w pamięci po zakończeniu 
działania funkcji.

4.

Zmienne zadeklarowane w liście parametrów funkcji są zmiennymi lokalnymi 
funkcji.

5.

Zmienne zadeklarowane w bloku są widoczne tylko w jego wnętrzu (w tym w 
jego zagnieŜdŜeniach).

background image

C/C++ - zasięg deklaracji zmiennych



Zmienne globalne są widoczne w kaŜdym miejscu w programie.

#include <conio.h>    

#include <iostream>

int zmienna_globalna=44444; // deklaracja zmiennej globalnej

void funkcja()  

{

cout<<zmienna_globalna;   //u

Ŝ

ycie zmiennej globalnej

}

int main()                              

{

cout<<zmienna_globalna; // u

Ŝ

ycie zmiennej globalnej

getch();

return(0);

}

przykład

background image

C/C++ - zasięg deklaracji zmiennych



Zmienne lokalne  są widoczne tylko w funkcji gdzie zostały 
zadeklarowane (równieŜ te klasy static).

#include <conio.h>    

#include <iostream>

void funkcja()  

{

int zm_lok_1=333;  //zmienna klasy auto

static int  zm_lok_2=444; // zmienna klasy static

}

int main()                              

{  

funkcja();

cout<<zm_lok_1; //b

łą

d - zmienna lokalna funkcji "funkcja"

cout<<zm_lok_2; //b

łą

d - zmienna lokalna funkcji "funkcja"

return(0);

}

przykład

background image

C/C++ - zasięg deklaracji zmiennych



Zmienne zadeklarowane w liście parametrów funkcji są zmiennymi 
lokalnymi funkcji

#include <iostream>

#include <conio.h>

double trojkat(float &a,float b, float c)

{

double y;

y=a+b+c;

a=(a*b)/2;

return y;

}

main()

{

//float

a=3,b=4,c=5;

//  błąd -niezadeklarowane  zmienne

cout<<"obwod trojkata wynosi "<<trojkat(a,b,c);

cout<<"\na jego pole: "<<a;

return 0;                   

}

przykład

background image

C/C++ - zasięg deklaracji zmiennych



Zmienne zadeklarowane w bloku są widoczne tylko w jego wnętrzu (w 
tym w jego zagnieŜdŜeniach).

#include <conio.h>

#include <iostream>

#include "losowanie.c"

main ()

{  const int N=2

M=3;

int  tab[N][M],p;

randomize;

for ( int i=0;i<N;i++)

// zmienna jest zmienn

ą

 lokaln

ą

 p

ę

tli for

for ( int j=0;j<M;j++){

// zmienna jest zmienn

ą

 lokaln

ą

 p

ę

tli for

p=random(100);

// wewn

ę

trznej, tu s

ą

 widoczne obie zmienne

tab[i][j]=p;

// oraz j

}

i=2;j=3;

// poza p

ę

tlami zmienne i oraz j nie s

ą

 widoczne,

getch();

// zostały ju

Ŝ

 zniszczone a pami

ęć

 im przydzielona zwolniona

return(0);

}

przykład

background image

C/C++ - przesłanianie zmiennych

W języku C, tak jak w innych językach programowania, nie jest 
moŜliwe zadeklarowanie dwóch zmiennych o identycznych nazwach 
w tym samym bloku. Nie moŜe być zatem dwóch zmiennych 
globalnych o tej samej nazwie, podobnie w jednej funkcji nie moŜe 
być dwóch zmiennych lokalnych o tym samym identyfikatorze, a 
takŜe w jednej pętli (w jednym bloku).

MoŜna jednak deklarować zmienne o tej samej nazwie, o ile są 
zmiennymi lokalnymi róŜnych funkcji lub znajdują się w róŜnych 
blokach tego samego poziomu (bloki nie są zagnieŜdŜone).

MoŜna  w funkcji zadeklarować zmienną (lokalną) o takiej samej 
nazwie jak zmienna globalna. Wówczas w funkcji zmienna 
lokalna przesłania zmienn
ą globalną i to na niej są wykonywane 
operacje realizowane w ramach funkcji. 

background image

C/C++ - przesłanianie zmiennych

Przykład

#include <conio.h>    

#include <iostream>

int x=444;      

// deklaracja zmiennej globalnej o nazwie x

void funkcja()  

{

int x=222;

// deklaracja zmiennej o nazwie x

cout<<x<<'\n';   

//operacja zu

Ŝ

yciem zmiennej lokalnej

}          

// zmienna lokalna przesłoniła zmienn

ą

 globaln

ą

int main()                              

{    cout<<x<<'\n'; // u

Ŝ

ycie zmiennej globalnej

funkcja();

cout<<x;

getch();

return(0);

}

przykład