Funkcje Modularyzacja : program główny , funkcje 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
void D2P( int *n ) // przekazywanie wskaźnika { *n = *n + 2; // krok 2 } int a = 5; D2P( &a ); // krok 1
void D2R(int& n) // przekazywanie referencji { n = n + 2; // krok 2 } int a = 5; D2R( a ); // krok 1
long b = 5; D2R( b ); // krok 1 program główny funkcja D2R b tt n & 5 7 &
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 ) * ... // > 0 int 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; // poprawnie pf = & Ki; // poprawnie pf = 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 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 ); // heapSort Sort( 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; s += TD[i]; }
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 C void druk( int i ) { ... } // wersja I void druk( float f ) { ... } // wersja F void druk( char *s ) { ... } // wersja S int a; druk( a ); // zgodność: wersja I druk( 'a' ); // zgodność: wersja C druk( "a" ); // zgodność: wersja S long l; druk( l ); // błąd: niejednoznaczność // możliwe wersje C, I, F float f, *pf = &f; druk( f ); // zgodność: wersja F druk( pf ); // błąd: niezgodność
Zasada minimalizacji liczby konwersji 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( 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
int min(int a, int b) // wersja I { return a < b ? a : b; } 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 // zastępuje wzorzec template <class T> T min( T a, T b ) { return a < b ? a : b; } // min( 1, 2 ); // poprawnie: wersja I min( 3, 1.5 ); // błąd: niejednoznaczność Templa
Łączenie wielu plików programu · dyrektywa #include · pliki nagłówkowe · deklaracja extern External