Funkcje
Modularyzacja : program główny , funkcje
Funkcje :
– obliczające wartość
– nie obliczające wartości
Niedozwolone :
– zagnieżdżanie
– wywoływanie niezadeklarowanych
( deklaracje i definicje )
Deklaracja funkcji
typ identyfikator_funkcji (lista_argumentów_formalnych );
typ wartości funkcji : liczbowy, wskaźnikowy, referencyjny, strukturowy
sygnatura funkcji : liczba i typy argumentów formalnych
argument_formalny : typ identyfikator
int f1( int x, int y );
float wartosc( float cena, int liczba );
char* odpowiedz ( char *pytanie );
double alfa( double x1, x2 ); // błąd
max( int k, int l ); // typ domyślny int
// przestarzałe
void druk( char *napis ); // bez wyniku
Definicja funkcji
typ identyfikator_funkcji (lista_argumentów_formalnych )
{ blok }
blok : ciąg deklaracji, definicji i instrukcji wykonywany :
– do końca bloku
– do instrukcji return
argument_formalny : typ identyfikator
float sqr( float x ){ return x * x ;}
void max( int *m, int a, int b ){ *m = a > b ? a : b ;} // return;
void DrukujWynik ( float x ){
printf ( "\nWynik : %10.2f" , x);}
int split( char *S, char *D1, char *D2 ){ int licz_S = 0 ; // zmienna lokalna while ( *S ) { if ( licz_S & 0x01 ) *D2++ = *S++; else *D1++ = *S++; licz_S++; } *D1 = *D2 = 0; return licz_S;}
Wywołanie funkcji
identyfikator_funkcji ( lista_argumentów_aktualnych )
argument_aktualny : wyrażenie
a = 1 + sqr( 1.25 ); // w wyrażeniu
max( &lepsza, cena_1, cena_2 ); // instrukcja
sqr(3 + b * d );
DrukujWynik ((sqrt(delta) - 4 * a * c ) /
( 2 * a ) ) ;
printf( "\n%d\t%d\n", a + 2, a - 1 );
Powiązanie argumentów aktualnych i formalnych
int Funa ( int a, int b, int c )
{
if ( a > 3 * b – 1)
return c + 2;
else
return c * c + 1;
}
int k, r;
// .........
int x = Funa (12, k + 4, r - 3);
// a = 12, b = k + 4, c = r - 3
Przekazywanie argumentów do funkcji
zgodny typ argumentu formalnego i aktualnego :
– typy identyczne
– możliwa konwersja
long suma( long x )
{
return x + 1000;
}
suma(3); // poprawnie int -> long
suma(1543443L); // poprawnie bez konwersji
suma(17.8); // ryzykownie double -> long
suma('A'); // poprawnie char -> long
suma("ALA"); // błąd, konwersja niemożliwa
int oblicz( float *wf );
int *wi;
oblicz( wi );
// błąd, nieodpowiedni wskaźnik
oblicz (( float*) wi);
// poprawnie, ryzykownie
Sposoby przekazywania argumentów
przekazywanie wartości
przekazywanie wskaźnika
przekazywanie referencji
void D2V ( int n ) // przekazywanie wartości{ n = n + 2; // krok 2}int a = 5;D2V ( a ); // krok 1
a
a
n
n
krok 1
krok 2
program główny funkcja D2V
5 5
5 7
void D2P( int *n ) // przekazywanie wskaźnika{ *n = *n + 2; // krok 2}int a = 5;D2P( &a ); // krok 1
a
a
n
n
krok 1
krok 2
program główny funkcja D2P
7
5
void D2R(int& n) // przekazywanie referencji{ n = n + 2; // krok 2}int a = 5;D2R( a ); // krok 1
a
a
n
n
krok 1
krok 2
program główny
7
&
&
5
funkcja D2R
long b = 5;
D2R( b ); // krok 1
program główny funkcja D2R
b tt n
5 5 &
5 7 &
krok 1
krok 2
struct Konto{
long numer;long suma;
}void Wplata ( Konto kk, long kwota){
kk.suma += kwota;}Konto AB = { 84404, 0 };Wplata ( AB, 3285 ); // AB.suma == ?
Konto Wplata ( Konto kk, long kwota)
{
kk.suma += kwota;
return kk;
}
AB = Wplata ( AB, 3285 ); // AB.suma == 3285
Argument stały
float PoleKola(const float *lpi, float *pr)
{
*lpi = 2.5; // błąd
... } Podatek, ONP, SumIloFun
Tablice jako argumenty funkcji
• Tablice jednowymiarowe
int FT(int *); // deklaracje
int FT(int[ ]);
int FT(int[10]);
int FT(int *T) { ... } // definicje
int FT(int T[ ]) { ... }
int FT(int T[10]) { ... }
// T [ 3 ]
// T + 3 * sizeof ( int )
void ZAP1( int T[100] )
{
for ( int i = 0; i < 100; ++i )
T[ i ] = i;
}
//
int ALFA[15];
ZAP1 ( ALFA ) ; // zapis + niszczenie
int BETA[100];
ZAP1 ( &BETA [0] ); // zapis całej tablicy
int GAMMA[150];
ZAP1 ( GAMMA ); // zapis 2/3 tablicy
void ZAP2(int T[ ], int rozmiar)
{
for ( int i = 0; i < rozmiar; ++i )
T[i] = i;
}
• Tablice wielowymiarowe
wszystkie wymiary tablicy, poza najstarszym ( pierwszym od lewej )
void ZAP3( float TT[ ][10], int wierszy ){ for (int i = 0; i < wierszy; ++i) for (int j = 0; j < 10; ++j) TT[i][j] = i + j;}// TT [ 3 ] [ 5 ]// TT + 3 * 10 * sizeof ( float ) + 5 * sizeof ( float )
TabDem,EwTelFun
Wartości domyślne argumentów funkcji
float SUM3(float x, float y = 2.5, float z = 3.5)
{ return x + y + z; }
float a, b, c;
SUM3( a, b, c ); // a + b + c
SUM3( a, b ); // a + b + 3.5
SUM3( a ); // a + 2.5 + 3.5
SUM3( ); // błąd
SUM3( a, ,c ); // błąd
long Dotacja( const char *Osoba, long Kwota = 100 );
long Dotacja
(const char *Osoba = "Jan Kowalski" , long Kwota )
{ ......... }
void F1 (int = 8, int, int = 5, long = 3);
void F1 (int x, int y = 4, int z, long g )
{ ......... }
Funkcje rekurencyjne
n * ( n - 2 ) * ( n - 4 ) * ... // > 0int IR ( int n ){ return n <= 0 ? 1 : n * IR( n – 2 );}int IP ( int n ){ int s = 1; while ( n > 0 ) { s *= n; n -= 2; } return s; }
Podprogramy wstawiane
inline double WB(double x, double y, double z)
{
return x > y ? z : x;
}
Hash
Wskaźniki funkcji
int ( *pf )( int, int ); // typ wyniku i sygnatura
int Ki( int x, int y ){ return (x + y) * (x + 2 * y);}long Kl( int x, int y ){ return (long)(x + 3 * y) * (x - y);}pf = Ki; // poprawniepf = & Ki; // poprawniepf = Kl; // błąd, nieodpowiedni wskaźnik
void bubbleSort ( float T[ ], int n ) { ... }
void mergeSort ( float T[ ], int n ) { ... }
void heapSort ( float T[ ], int n ) { ... }
void ( *wS )( float[ ], int ) = bubbleSort;
void ( *nS )( float[ ], int ) ;
nS = wS;
float TAB[ 150 ];
wS ( TAB, 150 );
( *nS )( TAB, 150 );
/* równoważne wywołania funkcji bubbleSort */
Tablice wskaźników funkcji
int fA(double x) { ... }
int fB(double y) { ... }
int fC(double z) { ... }
int ( *fX [3] )( double ) = { fA, fB };
fX[2] = fC;
fX[1]( 37.18 ); // wywołanie
int ( *Test [10] )( char* ) = { ...... };
int Wyniki [10];
char* Napisy[10];
for (int i = 0; i < 10; ++i )
Wyniki[i] = Test[i] ( Napisy[i] );
//
//
typedef int ( *PF )( float, float );
int Fun( float a, float b ) { ... }
PF f1, f2 = Fun;
PF Tfun[15];
Wskaźnik funkcji jako argument funkcji
void Sort( float[ ], int, void (*) ( float[ ], int ) = mergeSort );void Sort(float TAB[ ], int rozmiar, void (*fS) (float[ ], int) ){ ................. fS( TAB, rozmiar ); ................. }float T1[100], T2[200];void ( *wF )( float[ ], int ) = heapSort;Sort( T1, 100, bubbleSort );Sort( T2, 200, wF ); // heapSortSort( T2, 200 ); // mergeSort
Wskaźnik funkcji jako wynik funkcji
typedef char* ( *NP )( char*, char* );
struct FUNKCJE{ int cecha; NP funkcja;} TABLICA[15];
NP Szukaj( FUNKCJE TAB[ ], int rozmiar, int wzorzec )
{ for (int i = 1; i < rozmiar; ++i)
if (TAB[i].cecha == wzorzec) return TAB[i].funkcja;
return TAB[0].funkcja; }
//
printf
( "%s\n" ,
Szukaj ( TABLICA, 15, 1527 )( "Alf","Ogi")
); Kalku, MatFun, Oferta
Przeciążanie identyfikatorów funkcji
int SA( int TI[ ], int n ){ int s = 0; for (int i = 0; i < n; ++i) s += TI[i]; return s / n;} double SA( double TD[ ], int n ){ double s = 0; for (int i = 0; i < n; ++i) s += TD[i]; return s / n;}
int TAB_I [ 10 ];
double TAB_D [ 10 ];
SA ( TAB_I, 10);
SA ( TAB_D, 10);
// wyboru dokonuje kompilator
Różne sygnatury : przeciążenie identyfikatora
Równe sygnatury :
równe typy wyniku : przesłanianie
różne typy wyniku : błąd
/* plik funkcji bibliotecznych */int strlen( char *s ); /* plik programu użytkowego */int strlen( char *z ){ int len = 0; while (*z++) if (*z != ' ') ++len; return len; }/* definicja zawarta w pliku programu użytkowego przesłania deklarację z pliku bibliotecznego */
void czytaj(char *) { ... }int czytaj(char *) { ... } // błąd
Wybór wersji funkcji o przeciążonym identyfikatorze
zgodność : typ taki sam lub konwersja
niezgodność : konwersja niemożliwa
niejednoznaczność : zgodność w kilku funkcjach
void druk( char c ) { ... } // wersja Cvoid druk( int i ) { ... } // wersja Ivoid druk( float f ) { ... } // wersja Fvoid druk( char *s ) { ... } // wersja S int a;druk( a ); // zgodność: wersja Idruk( 'a' ); // zgodność: wersja Cdruk( "a" ); // zgodność: wersja S
long l;
druk( l ); // błąd: niejednoznaczność
// możliwe wersje C, I, Ffloat f, *pf = &f;druk( f ); // zgodność: wersja Fdruk( pf ); // błąd: niezgodność
Zasada minimalizacji liczby konwersji
void ff( int k, float z ) { ... } // wersja 1
void ff( char c, float z ) { ... } // wersja 2
//
ff( 'a', 15 ) // ?
Wartości domyślne argumentów
void fun( int n ) {... } // wersja 1
void fun( long l, int n = 0 ) { } // wersja 2
fun( 2L ); // wersja 2: fun (2L, 0);
fun( 5, 38 ); // wersja 2: fun (5, 38);
fun( 137 ); // wersja 1: fun (137);
fun( 3.14 ); // błąd: niejednoznaczność
Tekst
Wzorce funkcji
int min(int a, int b) // wersja I{ return a < b ? a : b; }long min(long a, long b) // wersja L{ return a < b ? a : b; }float min(float a, float b) // wersja F{ return a < b ? a : b; }// zastępuje wzorzectemplate <class T> T min( T a, T b ){ return a < b ? a : b; }//min( 1, 2 ); // poprawnie: wersja Imin( 3, 1.5 ); // błąd: niejednoznaczność
Templa
Łączenie wielu plików programu
dyrektywa #include
pliki nagłówkowe
deklaracja extern
External