ΣΥΝΑΡΤΗΣΕΙΣ (Functions) Δομή Συνάρτησης τύπος όνομα ( λίστα τυπικών παραμέτρων ) Δηλώσεις μεταβλητών εντολή_1 εντολή_2 : εντολή_ν Σώμα της συνάρτησης
Δομή της Λίστας Τυπικών Παραμέτρων τύπος_1 τύπος_2 τύπος_3 : : τύπος_ν παράμετρος_1, παράμετρος_2, παράμετρος_3, παράμετρος_ν Παράδειγμα λίστας τυπικών παραμέτρων int a, double x, float y, char xar
Παράδειγμα void ektyposi_epilogon(void) printf( Εισάγετε 1 για τη μέθοδο 1\n ); printf( Εισάγετε 2 για τη μέθοδο 2\n ); printf( Εισάγετε 3 για τη μέθοδο 3\n );
Κλήση Συνάρτησης όνομα-συνάρτησης (λίστα πραγματικών παραμέτρων); Παράδειγμα κλήσης ektyposi_epilogon (); Δήλωση Συνάρτησης (Πρωτότυπο) τύπος όνομα-συνάρτησης (λίστα τυπικών παραμέτρων) ; Παράδειγμα δήλωσης void ektyposi_epilogon( void ) ; ή void ektyposi_epilogon(); /*δεν συνιστάται*/
Παράδειγμα Να γραφεί πρόγραμμα που να καλεί την συνάρτηση ektyposi_epilogon. Πρόγραμμα #include <stdio.h> void ektyposi_epilogon (void); /*Πρωτότυπο Συνάρτησης*/ int main(void) ektyposi_epilogon(); /*κλήση*/ return 0;
/*ορισμός της συνάρτησης*/ void ektyposi_epilogon(void) printf( Εισάγετε 1 για τη μέθοδο 1 \n ); printf( Εισάγετε 2 για τη μέθοδο 2\n ); printf( Εισάγετε 3 για τη μέθοδο 3\n );
Συναρτήσεις που επιστρέφουν μία τιμή Ηεντολή return return ( παράσταση ) ; Αν δεν επιστρέφει μία τιμή (τύπος=void) τότε η return μπορεί να παραλειφθεί(συνιστάται) ή return;
Παράδειγμα Να γραφεί πρόγραμμα που να καλεί την συνάρτηση ektyposi_epilogon. Στη συνέχεια να ελέγχεται η ορθότητα της απάντησης του χρήστη.
Πρόγραμμα #include <stdio.h> /*Πρωτότυπα συναρτήσεων*/ void ektyposi_epilogon (void); int epilogi_xristi(void); int main(void) /*Δηλώσεις μεταβλητών*/ int epilogi; char synexisete = n ; /* n(ai) */ /*Σώμα συνάρτησης*/
while (synexisete == n ) epilogi = epilogi_xristi(); printf( Επιθυμείτε να συνεχίσετε; (n/o): ); scanf( %c, &synexisete); getchar(); /* διαβάζει το CR */ return 0; /*Σκοπός: Έλεγχος δεδομένων από το χρήστη. Δέχεται: Κανένα δεδομένο. Επιστρέφει: epilogi*/
int epilogi_xristi(void) /* δηλώσεις μεταβλητών*/ char sosti_epilogi = ο ;/* oxi */ int epilogi; /*Σώμα συνάρτησης*/ while (sosti_epilogi == ο ) ektyposi_epilogon(); scanf( %d, &epilogi);
if (epilogi ==1 epilogi == 2 epilogi ==3) sosti_epilogi = n ; /*Επιστροφή της τρέχουσας τιμής της epilogi κάτω από το όνομα της συνάρτησης*/ return epilogi;
/*ορισμός της συνάρτησης*/ void ektyposi_epilogon(void) printf( Εισάγετε 1 για τη μέθοδο 1 \n ); printf( Εισάγετε 2 για τη μέθοδο 2\n ); printf( Εισάγετε 3 για τη μέθοδο 3\n );
ΣΥΝΑΡΤΗΣΕΙΣ ΜΕ ΠΑΡΑΜΕΤΡΟΥΣ Τυπικές Παράμετροι Παράμετροι τιμών Παράμετροι δεικτών (value) (pointers) Μεταβλητές εισόδου Μεταβλητές εξόδου
Παράδειγμα Το πρωτότυπο συνάρτησης που δέχεται τρεις ακέραιους αριθμούς και επιστρέφει το μεγαλύτερο, μπορεί να είναι το εξής: int megistos (int x, int y, int z); /*συνιστάται*/ ή int megistos( int, int, int ); /*δεν συνιστάται*/ ή int megistos(x, y, z); int x, int y, int z; Παράδειγμα Γράψτε μία συνάρτηση που να προσδιορίζει το πρόσημο ενός αριθμού.
/*Σκοπός : Προσδιορίζει το πρόσημο ενός αριθμού. Δέχεται : Έναν πραγματικό αριθμό. Επιστρέφει: Το πρόσημο ενός αριθμού κάτω από το όνομα της συνάρτησης*/ char prosimo (float arithmos) if (arithmos < 0) return - ; else /*Σώμα συνάρτησης*/ return + ;
Παράδειγμα Γράψτε μία συνάρτηση που να βρίσκει το μεγαλύτερο από τρεις ακέραιους αριθμούς Συνάρτηση /*Σκοπός: Προσδιορίζει το μεγαλύτερο από τρεις ακέραιους αριθμούς. Δέχεται: Τρεις ακέραιους αριθμούς. Επιστρέφει: Το μεγαλύτερο ακέραιο κάτω από το όνομα της συνάρτησης*/
int megistos (int ar1, int ar2, int ar3) τυπικές μεταβλητές int meg; /* Τοπική μεταβλητή */ if (ar1 > ar2) meg = ar1; else meg = ar2; /*meg = max ( meg1, meg2) */ if (ar3 > meg) meg = ar3; return (meg);
Παράδειγμα Γράψετε ένα πρόγραμμα που να βρίσκει το μεγαλύτερο από πέντε ακέραιους αριθμούς χρησιμοποιώντας τη συνάρτηση megistos Ανάλυση pros1=megistos(num1, num2, num3); pros2=megistos(num4, num5, pros1); Πραγματικές Παράμετροι
Πρόγραμμα #include <stdio.h> /*Πρωτότυπα συναρτήσεων*/ int megistos (int ar1, int ar2, int ar3); int main(void) int num1, num2, num3, num4, num5; int pros1, pros2; printf( Εισάγετε 5 ακέραιους αριθμούς: ); scanf( %d %d %d %d %d, &num1, &num2, &num3, &num4, &num5);
pros1 = megistos (num1, num2, num3); pros2 = megistos (num4, num5, pros1); πραγματικές παράμετροι printf( Ο μεγαλύτερος είναι ο: %d, pros2); return 0; /*Σκοπός: Προσδιορίζει το μεγαλύτερο από τρεις ακέραιους αριθμούς. Δέχεται: Τρεις ακέραιους αριθμούς. Επιστρέφει: Το μεγαλύτερο ακέραιο κάτω από το όνομα της συνάρτησης*/
int megistos (int ar1, int ar2, int ar3) int meg; if (ar1 > ar2) meg = ar1; else meg = ar2; if (ar3 > meg) meg = ar3; return (meg);
Παράδειγμα Γράψτε ένα πρόγραμμα που να υπολογίζει και τυπώνει τον n-ιοστό αριθμό της ακολουθίας Fibonacci. Η ακολουθία Fibonacci 0 1 1 2 3 5 8 13...
Πρόγραμμα #include <stdio.h> /*Πρωτότυπα συναρτήσεων*/ int fibonacci (int n); int main(void) int n, fib; printf( Εισάγετε ένα θετικό ακέραιο: ); scanf( %d, &n); fib = fibonacci(n); printf( Ο %d -οστός αριθμός είναι: %d, n, fib);
return 0; /*Σκοπός: Υπολογίζει τον n-ιοστό αριθμό fibonacci. Δέχεται: Ένα θετικό ακέραιο αριθμό. Επιστρέφει: Τον αριθμό fibonacci.*/ int fibonacci (int n) int protos = 0, deyteros = 1, metritis = 3, arithmos; if (n == 1) arithmos = protos; else
if (n == 2) arithmos = deyteros; while (metritis <= n) arithmos = protos + deyteros; protos = deyteros; deyteros = arithmos; metritis++; return (arithmos);
Παράδειγμα Γράψτε μια συνάρτηση που να υπολογίζει και τυπώνει την τιμή της σειράς: 2 3 x x x 1- + - + 1! 2! 3! για μια δεδομένη τιμή του x. Οι όροι της σειράς αθροίζονται μέχρις ότου κάποιος από αυτούς γίνει μικρότερος από ε κατά απόλυτο τιμή, όπου ε=0.5 10-6.
float series (float x, float epsilon) float oros = 1.0, athroisma = 1.0; int n = 1; while (abs(oros) > epsilon) oros *= -x/n; athroisma += oros; ++n; return (athroisma);
Παράδειγμα Γράψτε ένα πρόγραμμα που να χρησιμοποιεί την συνάρτηση series, προκειμένου να υπολογίζει με γνωστή ακρίβεια ε την τιμή της σειράς: 2 3 x x x 1- + - + 1! 2! 3! για άγνωστο πλήθος δεδομένων (x, ε). Κάθε ζεύγος τιμών για τις x και ε δίνεται από το πληκτρολόγιο.
Πρόγραμμα #include <stdio.h> #include <math.h> float series(float x, float epsilon); int main(void) float x1, eps, timi; char apantisi = n, nea_grammi; while (apantisi == n ) printf( Εισάγετε τα x και ε: );
scanf( %f %f, &x1, &eps); timi = series (x1, eps); printf( \n %7.3f %e %7.3f, x1, eps, timi); printf( Επιθυμείτε να συνεχίσετε; (n/o): ); scanf( %c, &apantisi); getchar(); /* διαβάζει το CR */ return 0;
Να γραφεί μία συνάρτηση, η οποία να επιστρέφει 2 την τιμή του i για δεδομένο n. Συνάρτηση int athroisma_tetr (int n) int i, athroisma= 0; for (i=1; i <= n; ++i) athroisma += i*i; return (athroisma); n i=1
/*Η χρήση της ανωτέρω συνάρτησης σε ένα πρόγραμμα γίνεται ως εξής:*/ #include <stdio.h> #define N 5 int main(void) int n; for (n=1; n <= N; ++n) printf( \n%5d, athroisma_tetr(n)); printf( \n\n ); return 0;
Παράδειγμα Να γραφεί συνάρτηση, η οποία να επιστρέφει n k την τιμή του i για δεδομένα n και k. i=1
Καταρχήν θα γράψουμε μία συνάρτηση, η οποία επιστρέφει τις τιμές της δύναμης m n για δεδομένα m και n. Συνάρτηση int dynami (int m, int n) int i, ginomeno = 1; for (i=1; i <= n; ++i) ginomeno *= m; return (ginomeno);
Συνάρτηση int athroisma_dyn (int k, int n) int i, athroisma = 0; for (i=1; i <= n; ++i) athroisma += dynami (i, k); return (athroisma); n i i=1 k
Κλάσεις αποθήκευσης auto, register, static, extern void ypologismos (void) static int fores = 0;.. εντολές. fores++; printf( Η συνάρτηση κλήθηκε %d φορές, fores);
Εμβέλεια #include <stdio.h> int b, c, d; /* καθολικές μεταβλητές */ void e(float f, float g, float h); int main(void) /* σώμα εντολών */ return 0; void e(float f, float g, float h) /* f, g, h, i, j τοπικές μεταβλητές */ int i,j; /* σώμα εντολών */
Πρόγραμμα #include <stdio.h> int d; /*καθολική μεταβλητή*/ void sygxisi (int a, int b); int main(void) int a, b, c; /*τοπικές μεταβλητές στη main*/ a = 1; b = 2; c = 3; d = 4;
printf( \n%8d %8d %8d %8d, a, b, c,d); sygxisi (a, b); printf( \n%8d %8d %8d %8d, a, b, c, d); void sygxisi (int a, int b) float c; /*τοπική μεταβλητή*/ a = 5; b = 6; c = 7.3; d = 8; /*άσχημος προγραμματισμός! */ printf( \n%8d %8d %8.1f %8d, a, b, c, d);
Ηεκτύπωση θα είναι η ακόλουθη 1 2 3 4 5 6 7.3 8 1 2 3 8
Παραδείγματα ΔΕΙΚ Τ Ε Σ (pointers) int *arith_dktis; char *xarakt_dktis; int x = 10, *p, *q; p = 0; p = NULL; p = &x; q = p; p q x 10
Παράδειγμα double x = 3.1, y, *p; p = &x; y = *p; p x 3.1 *p Οι ανωτέρω εντολές είναι ισοδύναμες με την y = *&x; η οποία είναι ισοδύναμη με την y = x;
ΔΕΙΚ Τ Ε Σ (pointers) int *p, *q, x, y; p=&x; q=&y; p x q y
*p=5; *q=8; p 5 q 8 p=q; p 8 p 5 q 8 q 8 λάθος σωστό
*p=5; *q=8; p 5 q 8 *p=*q; p 8 p 5 q 8 q 8 σωστό λάθος
Μεταβίβαση Ορισμάτων Κλήση με τιμή (call by value) Κλήση με αναφορά (call by reference)
void g(int k); int main(void) int a; a=1; g(a); printf( a=%d\n, a); return 0; void g( int k) k=k+1; a ΠΡΙΝ 1 a KATA k 1 1 k++ a k 1 2 a ΜΕΤΑ 1
void g(int *k); int main(void) int a; a=1; g( &a); printf( a=%d\n, a); return 0; k a ΠΡΙΝ 1 ΚΑΤΑ &a void g( int *k) *k=*k+1; k a 2 &a
float afksisi (float x); int main (void ) float x1, y; x1 = 1; y = afksisi (x1); printf ( %f, y); return 0; float afksisi (float x) x = x+1; return (x); Κλήση με τιμή Φάση Παράμετρος Περιεχόμενο Σχόλια Πριν την κλήση x1 1 Μετά την x1=1; Με την κλήση x 1 Νέα μετ/τή Πριν το τέλος x 2 x= x+1; Μετά την afksisi x1 1 Επισ/φή main H μεταβίβαση των ορισμάτων με τιμή αφήνει τις αρχικές τιμές τους στην καλούσα συνάρτηση αμετάβλητες (δημιουργεί αντίγραφα)
void afksisi (float *x); int main (void ) float x1; x1 = 1; afksisi (&x1); printf ( %f,x1); return 0; void afksisi (float *x) *x = *x+1; Κλήση με αναφορά Φάση Παράμετρος Περιεχόμενο Σχόλια Πριν την κλήση x1 1 Μετά την x1=1; Με την κλήση *x (x1) 1 δύο όνοματα Πριν το τέλος *x 2 *x=*x+1; Μετά την afksisi x1 2 πίσω στη main Η μεταβίβαση ορισμάτων με αναφορά χρησιμοποιείται μόνο για το πέρασμα αποτελεσμάτων στην καλούσα συνάρτηση καθόσον τροποποιεί τις αρχικές τους τιμές.
H μεταβίβαση ορισμάτων με αναφορά γίνεται όταν είναι αναγκαίο να επιστραφούν περισσότερα του ενός αποτελέσματα καθόσον μία συνάρτηση επιστρέφει μόνο ένα αποτέλεσμα. Επίσης όταν η ίδια η μεταβλητή χρησιμοποιείται για να παρέχει δεδομένα στην καλούμενη συνάρτηση και ταυτόχρονα να μεταφέρει αποτελέσματα στην καλούσα συνάρτηση.
#include <stdio.h> int d; /*καθολική μεταβλητή*/ void sygxisi(int a, int b); κλήση με τιμή int main (void ) int a,b,c; a = 1; b = 2; c = 3; d = 4; printf ( \n%8d %8d %8d %8d,a,b,c,d); sygxisi (a,b); printf ( %8d %8d %8d %8d,a,b,c,d); return 0;
void sygxisi(int a, int b) float c; /*τοπική μεταβλητή*/ a = 5; b = 6; c = 7.3; d = 8; printf ( %8d %8d %8.1f %8d,a,b,c,d); Ηεκτύπωση θα είναι η ακόλουθη 1 2 3 4 5 6 7.3 8 1 2 3 8
#include <stdio.h> int d; /*καθολική μεταβλητή*/ void sygxisi(int *a, int *b); Κλήση με αναφορά int main (void) int a,b,c; a = 1; b = 2; c = 3; d = 4; printf ( \n%8d %8d %8d %8d,a,b,c,d); sygxisi(&a, &b); printf ( %8d %8d %8d %8d,a,b,c,d); return 0;
void sygxisi (int *a, int *b) float c; *a = 5; *b = 6; /*τοπική μεταβλητή*/ c = 7.3; d = 8; printf ( %8d %8d %8.1f %8d,*a,*b,c,d); Τότε η εκτύπωση θα είναι η ακόλουθη 1 2 3 4 5 6 7.3 8 5 6 3 8
Πρόβλημα Γράψτε μία συνάρτηση που να εναλλάσει τις τιμές δύο μεταβλητών ακεραίου τύπου. Συνάρτηση void enalagi (int *proti, int *deyteri) /*Εναλλάσει τις τιμές δύο μεταβλητών*/ int prosorini; prosorini = *proti; *proti = *deyteri; *deyteri = prosorini;
Αναδρομή Αναγωγή του αρχικού προβλήματος σε μικρότερα προβλήματα του ίδιου τύπου Αν μια συνάρτηση περιέχει μια κλήση του εαυτού της στο εσωτερικό του τμήματος των εντολών της, τότε λέγεται ότι είναι μία αναδρομική συνάρτηση (recursive function) Δομή αναδρομικής συνάρτησης Κατάσταση διακοπής Αναδρομικό βήμα Πρόβλημα Να γραφεί μια αναδρομική συνάρτηση που να υπολογίζει το παραγοντικό ενός μη αρνητικού ακεραίου αριθμού.
Ανάλυση n! = n(n-1)!, 0! = 1 Αν n = = 0 τότε να επιστραφεί η τιμή 1 (κατάσταση διακοπής) Αν n 1, τότε να επιστραφεί η : n * factorial (n-1) (αναδρομικό βήμα) Υλοποίηση int factorial (int n) if (n = = 0) /* Κατάσταση διακοπής */ return 1; else return (n * factorial (n-1)); /* Αναδρομικό βήμα */
Εκτέλεση της factorial(3); Αναδρομικό επίπεδο 0 factorial(3) 6 1 3 * factorial(2) 2 2 2 * factorial(1) 1 3 1 * factorial(0) 1
Εντολές μετά την αναδρομική κλήση Πρόβλημα Να γραφεί ένα πρόγραμμα που να διαβάζει μια γραμμή χαρακτήρων και να την τυπώνει με την αντίστροφη φορά. #include <stdio.h> void stoivaxeharaktires (void ); int main (void ) printf ( \nδώστε μία σειρά χαρακτήρων : ); stoivaxeharaktires ( ); printf ( \n\n ); return 0;
void stoivaxeharaktires (void ) char xar; scanf ( %c, &xar); if (xar!= \n ) stoivaxeharaktires ( ); printf ( %c, xar);
Αναδρομικό Προς τα πίσω Ενέργεια επίπεδο διαδικασία 1 scanf ( %c, &xar); Διαβάζεται ο Τ 2 scanf ( %c, &xar); Διαβάζεται ο h 3 scanf ( %c, &xar); Διαβάζεται ο e Αναδρομικό Προς τα εμπρός Ενέργεια επίπεδο διαδικασία 3 printf ( %c, &xar); Τυπώνεται o e 2 printf ( %c, &xar); Τυπώνεται o h 1 printf ( %c, &xar); Τυπώνεται o T
int Fibonacci (int n) if (n <=0) return 0; else if (n == 1) return 1; else Οι αριθμοί Fibonacci = 0, F = 1, 0 1 F = F + F, n 2 n n 1 n 2 return (Fibonacci (n 1) + Fibonacci (n 2)); F
Αναδρομικό δέντρο για τον υπολογισμό του F5 F5 F4 F3 F3 F2 F2 F1 F2 F1 F1 F0 F1 F0 F1 F0
Οι συναρτήσεις σαν ορίσματα Αν θέλουμε να γράψουμε μια συνάρτηση που να υπολογίζει το: Τότε θα είχαμε: double f (int k) /*Σώμα της f ()*/ n k= m f ( k)
double athroisma (int m, int n) int k; double athr = 0.0; for (k = m; k <= n; ++k) athr += f (k); return (athr); Μπορούμε να βάλουμε την f σαν όρισμα στην athroisma, για να την καλούμε για οποιαδήποτε συνάρτηση f. Η δήλωση: double (*f) (); σημαίνει ότι η f είναι ένας δείκτης σε μια συνάρτηση που δεν έχει παραμέτρους και επιστρέφει αποτέλεσμα double.
Τώρα, η athroisma γίνεται: double athroisma (double (*f) (), int m, int n) int k; double athr = 0.0; for (k = m; k <= n; ++k) athr += (*f) (k); return (athr); Στη συνέχεια δίνουμε τα υποπρογράμματα και την main για τις συναρτήσεις f 1 (k) = k και f 2 (k) = k 2.
/*Υπολογίζει το άθροισμα των 10 πρώτων ακεραίων αριθμών και το άθροισμα των τετραγώνων τους*/ #include <stdio.h> /*Πρωτότυπα συναρτήσεων*/ double f1 (int k1); double f2 (int k2); double athroisma (double (*f) (), int m, int n); main () printf( \n%.5f %.5f\n\n, athroisma(f1, 1, 10), athroisma(f2, 1, 10));
double f1 (int k1) return (k1); double f2 (int k2) return (k2 * k2);