Συναρτιςεισ Μζροσ 2 ο Βαγγζλθσ Οικονόμου Διάλεξθ 7 1
Περιεχόμενα Βιβλιοκικεσ τθσ C Μεταβίβαςθ παραμζτρων παράδειγμα swap Αναδρομικότθτα Συναρτιςεισ και Πίνακεσ 2
H βαςικι βιβλιοκικθ τθσ C Η βαςικι βιβλιοκικθ τθσ C ορίηει ζνα ςφνολο από ςυναρτιςεισ που επιτελοφν βαςικζσ διεργαςίεσ. Η γνϊςθ των ςυναρτιςεων αυτϊν αποτελεί βαςικι προχπόκεςθ για τθν ανάπτυξθ ςφνκετων προγραμμάτων, όπου θ επαναχρθςιμοποίθςθ ζτοιμων ελεγμζνων τμθμάτων κϊδικα μειϊνει ςθμαντικά το χρόνο ανάπτυξθσ, αυξάνοντασ ταυτόχρονα τθν αξιοπιςτία. Είναι ςθμαντικό ςτθ φάςθ αυτι, να αποκαταςτιςετε μια πρόςβαςθ ςε τεκμθρίωςθ τθσ βαςικισ βιβλιοκικθσ και ςιγά ςιγά να εξοικειϊνεςτε με τισ ςυναρτιςεισ που αυτι περιζχει. 3
H βαςικι βιβλιοκικθ τθσ C Βαςικζσ Συναρτιςεισ: διαχείριςθσ αλφαρικμθτικϊν, μακθματικζσ, ταξινόμθςθσ/χειριςμοφ χαρακτιρων, μετατροπζσ χαρακτιρων και ειςόδου εξόδου Συναρτιςεισ προχωρθμζνου επιπζδου: μετατροπισ δεδομζνων, αναηιτθςθσ και ταξινόμθςθσ, διαχείριςθσ αρχείων και διαχείριςθσ μνιμθσ. 4
Συναρτιςεισ διαχείριςθσ αλφαρικμθτικϊν Όνομα βιβλιοκικθσ: string.h Ενδεικτικζσ ςυναρτιςεισ: char *strcpy(char *s1, char *s2): Αντιγράφει τθν ακολουκία χαρακτιρων s2 ςτον πίνακα s1. Επιςτρζφεται θ τιμι του s1 char *strncpy(char *s1, char *s2, size_t n): Αντιγράφει n χαρακτιρεσ από τθν ακολουκία χαρακτιρων s2 ςτον πίνακα s1. Επιςτρζφεται θ τιμι του s1 char *strcat(char *s1, char *s2): προςαρτά τθν ακολουκία s2 ςτον πίνακα s1. Επιςτρζφεται θ τιμι του s1 char *strncat(char *s1, char *s2, size_t n): προςαρτά n χαρακτιρεσ από τθν ακολουκία s2 ςτον πίνακα s1. Επιςτρζφεται θ τιμι του s1 int strcmp(char *s1, char *s2): Συγκρίνει τθν ακολουκία χαρακτιρων s1 με τθν ακολουκία s2. Επιςτρζφει 0 όταν s1=s2, >0 όταν s1>s2, <0 όταν s1<s2 5
Παράδειγμα /* strcpy example */ #include <stdio.h> #include <string.h> int main () { char str1[]="sample string"; char str2[40]; char str3[40]; strcpy (str2,str1); strcpy (str3,"copy successful"); printf ("str1: %s\n str2: %s\n str3: %s\n",str1,str2,str3); return 0; } Έξοδος προγράμματος: str1: Sample string str2: Sample string str3: copy successful 6
Μακθματικζσ Συναρτιςεισ Όνομα βιβλιοκικθσ: math.h Ενδεικτικζσ Συναρτιςεισ: double pow ( double base, int exponent ): επιςτρζφει τθν base εισ τθν exponent. double sqrt ( double x ): Επιςτρζφει τθν τετραγωνικι ρίηα του x. double log10 ( double x ): Επιςτρζφει τον λογάρικμο του x με βάςθ το 10. double cos ( double x ): Επιςτρζφει το θμίτονο μιασ γωνίασ x radians. double cos ( double x ): Επιςτρζφει το ςυνθμίτονο μιασ γωνίασ x radians. 7
Παράδειγμα /* sqrt example */ #include <stdio.h> #include <math.h> int main () { double param, result; param = 1024.0; result = sqrt (param); printf ("sqrt(%lf) = %lf\n", param, result ); return 0; } Έξοδος προγράμματος: sqrt(1024.000000) = 32.000000 8
Συναρτιςεισ Ταξινόμθςθσ/Χειριςμοφ Χαρακτιρων Ονομα Βιβλιοκικθσ: ctype.h Οι χαρακτιρεσ ςυχνά υπόκεινται ςε χειριςμοφσ ωσ ακζραιοι, επειδι ζνασ χαρακτιρασ ςτθ C είναι ζνασ ακζραιοσ ενόσ byte. Ενδεικτικζσ Συναρτιςεισ: int isdigit(int c): Επιςτρζφει τιμι 1 (true) αν ο c είναι ψθφίο, 0 (false) διαφορετικά. int isalpha(int c): Επιςτρζφει τιμι 1 (true) αν ο c είναι γράμμα, 0 (false) διαφορετικά int isalnum(int c): Επιςτρζφει τιμι 1 (true) αν ο c είναι γράμμα ι ψθφίο, 0 (false) διαφορετικά 9
Παράδειγμα /* isalpha example */ #include <stdio.h> #include <ctype.h> int main () { int i=0; char str[]="c++"; } Έξοδος προγράμματος: character C is alphabetic character + is not alphabetic character + is not alphabetic while (str[i]!= \0 ) { if (isalpha(str[i])==1) { printf ("character %c is alphabetic\n",str[i]); } else { printf ("character %c is not alphabetic\n",str[i]); } i++; } return 0; 10
Συναρτιςεισ ειςόδου - εξόδου Όνομα βιβλιοκικθσ: stdio.h Ενδεικτικζσ Συναρτιςεισ: int getchar(): Ειςάγει τον επόμενο χαρακτιρα από τθν τυπικι ζξοδο και τον επιςτρζφει ωσ ακζραιο char *gets( char *s): Ειςάγει τουσ χαρακτιρεσ από τθν τυπικι είςοδο ςτον πίνακα s μζχρι να βρεκεί ζνασ χαρακτιρασ νζασ γραμμισ ι τζλουσ αρχείου int putchar(int c): εμφανίηει ςτθν τυπικι ζξοδο τον χαρακτιρα που αποκθκεφςαμε ςτον c. int puts(char *s): εμφανίηει ςτθν τυπικι ζξοδο τθν ακολουκία χαρακτιρων του s, ακολουκοφμενθ από ζναν χαρακτιρα νζασ γραμμισ int sprintf(char *s, char *format, ): ιςοδφναμθ με τθν printf με τθν διαφορά ότι θ ζξοδοσ αποκθκεφεται ςτον πίνακα s. int sscanf(char *s, char *format, ): ιςοδφναμθ με τθν scanf με τθν διαφορά ότι θ είςοδοσ διαβάηεται από τον πίνακα s. 11
Παράδειγμα /* sprintf example */ #include <stdio.h> int main () { char buffer [50]; int n, a=5, b=3; n=sprintf (buffer, "%d plus %d is %d", a, b, a+b); printf ("[%s] is a %d char long string\n",buffer,n); return 0; } Έξοδος προγράμματος: [5 plus 3 is 8] is a 13 char long string 12
Συναρτιςεισ μετατροπισ χαρακτιρων Όνομα Βιβλιοκικθσ: stdlib.h Ενδεικτικζσ Συναρτιςεισ: double atof(char *nptr): μετατρζπει τθν ακολουκία χαρακτιτων nptr ςε double. double atoi(char *nptr): μετατρζπει τθν ακολουκία χαρακτιτων nptr ςε int. 13
Παράδειγμα /* atof example: sine calculator */ #include <stdio.h> #include <stdlib.h> #include <math.h> int main () { double n,m; double pi=3.1415926535; char szinput [256]; printf ( "Enter degrees: " ); gets ( szinput ); n = atof ( szinput ); m = sin (n*pi/180); printf ( "The sine of %f degrees is %f\n", n, m ); return 0; } Έξοδος προγράμματος: Enter degrees: 45 The sine of 45.000000 degrees is 0.707101 14
Μεταβίβαςθ Παραμζτρων παράδειγμα swap Η μεταβίβαςθ παραμζτρων (parameter passing) ςτθ C γίνεται με δφο τρόπουσ. κλιςθ κατά τιμι, κλιςθ κατ αναφορά Στθ μεταβίβαςθ με τιμι θ ςυνάρτθςθ δουλεφει πάνω ςε αντίγραφα των πραγματικϊν παραμζτρων, ενϊ ςτθ μεταβίβαςθ με αναφορά δουλεφει πάνω ςτισ πραγματικζσ παραμζτρουσ. (Θα μιλιςουμε για μεταβίβαςθ με αναφορά ςτο κεφάλαιο που κα αναλφςουμε τουσ δείκτεσ) 15
Μεταβίβαςθ Παραμζτρων παράδειγμα swap Πολλζσ φορζσ κζλουμε να ανταλλάξουμε μεταξφ τουσ τισ τιμζσ δφο μεταβλθτϊν. Πρόκειται για μια απλι διεργαςία θ οποία κα μποροφςε να αναπαραςτακεί από μία ςυνάρτθςθ με το παρακάτω πρωτότυπο/διλωςθ: void swap(int a, int b); Οριςμόσ ςυνάρτθςθσ: void swap(int a, int b) { int temp; temp = a; a = b; b = temp; } 16
Μεταβίβαςθ Παραμζτρων παράδειγμα swap Τζλοσ, μια πρόταςθ κλιςθσ τθσ ςυνάρτθςθσ swap κα μποροφςε να είναι θ swap(num1, num2); για τθν οποία ασ υποκζςουμε ότι οι num1 και num2 ζχουν τθ ςτιγμι τθσ κλιςθσ τιμζσ 12 και 102, αντίςτοιχα. Αν τυπϊςουμε πριν τθν κλιςθ τθσ swap τισ num1 και num2 κα πάρουμε ςαν ζξοδο τα 12 και 102. Το ίδιο ακριβϊσ αποτζλεςμα κα πάρουμε και μετά τθν κλιςθ τθσ swap. Αυτό ςθμαίνει πωσ θ swap δεν ζκανε ςωςτά τθν δουλειά τθσ. Και όμωσ, αν ςτον κϊδικα τθσ swap παρεμβάλω μια πρόταςθ με τθν printf για να δω τισ τιμζσ των a και b, κα παρατθριςω πωσ οι τιμζσ τουσ ζχουν αλλάξει. Τι ςυμβαίνει; 17
Μεταβίβαςθ Παραμζτρων παράδειγμα swap Απάντθςθ κα μασ δϊςει ο τρόποσ που λειτουργεί ο μθχανιςμόσ κλιςθσ. Οι τυπικζσ παράμετροι a και b ζχουν περιοριςμζνθ διάρκεια που ςθμαίνει πωσ δεςμεφεται χϊροσ ςτθ μνιμθ για τθν αποκικευςθ των τιμϊν τουσ με τθν είςοδο ςτθ ςυνάρτθςθ. Άρα, δθμιουργοφνται δφο νζα κελιά ςτθ μνιμθ τα οποία παίρνουν τισ τιμζσ των μεταβλθτϊν num1 και num2. 18
Αναδρομι Αναδρομικι Συνάρτθςθ: Συνάρτθςθ που καλεί τον εαυτό τθσ. Κεντρικι ιδεά: Σπάμε το πρόβλθμα ςε δφο τμιματα: ζνα τμιμα που θ ςυνάρτθςθ ξζρει να αντιμετωπίςει και ζνα τμιμα που θ ςυνάρτθςθ δεν ξζρει να αντιμετωπίςει 19
Αναδρομι Δϊςτε τθ διλωςθ και τον οριςμό μιασ ςυνάρτθςθσ που υπολογίηει το άκροιςμα των αρικμϊν από 1 μζχρι n. 1 θ λφςθ: Βρόχοσ for 2 θ λφςθ: Χριςθ αναδρομισ 20
Αναδρομι Ο υπολογιςμόσ του ακροίςματοσ n μπορεί να κεωρθκεί ςαν υπολογιςμόσ του ακροίςματοσ των αρικμϊν μζχρι το n 1 ςυν το n. O υπολογιςμόσ του ακροίςματοσ των αρικμϊν μζχρι τον n 1 μπορεί να γίνει από τθν ίδια ςυνάρτθςθ, αρκεί να τθσ περάςουμε το κατάλλθλο όριςμα δθλαδι το n 1. Ζτςι, οδθγοφμαςτε ςε μια πρόταςθ τθσ μορφισ return (sum(n 1) + n); 21
Αναδρομι Μζχρι πότε κα καλοφμε τθν ςυνάρτθςθ sum; κα πρζπει να τερματίςουμε τθ διαδικαςία κλιςθσ του εαυτοφ τθσ όταν το τυπικό τθσ όριςμα n πάρει τθν τιμι 1, οπότε και ο υπολογιςμόσ του ακροίςματοσ είναι απλόσ και δεν απαιτείται παραπζρα κλιςθ τθσ sum Αποκλειςτικι ευκφνθ του προγραμματιςτι ο τερματιςμόσ μιασ αναδρομικισ ακολουκίασ κλιςεων ςυναρτιςεων 22
Αναδρομι int sum(int n) { if (n =< 1) { return n; } else { return (sum(n 1) + n); } } 23
Συναρτιςεισ και Πίνακεσ Ζνασ πίνακασ είναι μια ομάδα ςυνεχόμενων κζςεων μνιμθσ που ζχουν το ίδιο όνομα και τον ίδιο τφπο. Για να αναφερκοφμε ςε μια ςυγκεκριμζνθ κζςθ ι ςτοιχείο ςτον πίνακα, κακορίηουμε το όνομα του πίνακα και τον αριθμό θέςησ του ςυγκεκριμζνου ςτοιχείου ςτον πίνακα. 24
Συναρτιςεισ και Πίνακεσ Για να διοχετεφςουμε ζναν πίνακα ςε μια ςυνάρτθςθ, περνάμε ςαν όριςμα ςτθν ςυνάρτθςθ το όνομα του πίνακα χωρίσ τισ αγκφλεσ. Παράδειγμα: int data[24]; //διλωςθ πίνακα modifyarray(data,24);//κλιςθ ςυνάρτθςθσ Όταν διοχετεφουμε ζνα πίνακα ςε μια ςυνάρτθςθ ςυχνά διοχετεφουμε και το μζγεκοσ του πίνακα ϊςτε θ ςυνάρτθςθ να μπορεί να επεξεργαςτεί το ςυγκεκριμζνο πλικοσ ςτοιχείων του πίνακα 25
Συναρτιςεισ και Πίνακεσ Η C διοχετεφει πίνακεσ ςε ςυναρτιςεισ χρθςιμοποιϊντασ «εικονικι» κλιςθ μζςω αναφοράσ Αποτζλεςμα: Οι κλθκείςεσ ςυναρτιςεισ μποροφν να τροποποιιςουν τισ τιμζσ των ςτοιχείων του πίνακα. Προςοχι: Η εικονικι κλιςθ μζςω αναφοράσ δεν λειτουργεί ςε μεμονωμζνα ςτοιχεία του πίνακα 26