C/C++
funkcje
postać, przekazywanie parametrów
argumenty funkcji main()
funkcje rekurencyjne
funkcje przeciążone
zasięg deklaracji zmiennych
przesłanianie zmiennych
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
C/C++ - funkcje
Ogólna postać funkcji jest następująca:
typ_rezultatu nazwa_funkcji(lista_parametrów)
{
ciało funkcji, czyli 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.
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.
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ę.
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;
}
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;
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
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;
}
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 [].
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);
}
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);
}
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);
}
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);
}
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);
}
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 []).
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] .
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);
}
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);
}
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
}
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
}
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
}
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.
#
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()
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;
}
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);
}
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.
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;
}
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).
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
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
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
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 i jest zmienn
ą
lokaln
ą
p
ę
tli for
for ( int j=0;j<M;j++){
// zmienna j jest zmienn
ą
lokaln
ą
p
ę
tli for
p=random(100);
// wewn
ę
trznej, tu s
ą
widoczne obie zmienne
tab[i][j]=p;
// i 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
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.
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