Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός (Διάλεξη 14) 14-1 Παράδειγμα: Αλλαγή τιμής μεταβλητής μόνο τοπικά ΛΑΘΟΣ τρόπος να αυξήσουμε το κατά 1 #include <stdio.h> void AddOne (int); void AddOne (int ) { main () ++; { rintf ( In AddOne: ); int = ; rintf ( = %d\n, ); AddOne (); } rintf ( In main: ); rintf ( = %d\n, ); } 6 To πρόγραμμα εκτυπώνει: In AddOne: =6 In main: = 14-2
Παράδειγμα (συνέχεια): Αλλαγή τιμής μεταβλητής με επιστροφή τιμής ΣΩΣΤΟΣ τρόπος να αυξήσουμε το κατά 1 #include <stdio.h> int AddOne (int); int AddOne (int ) { main () ++; { rintf ( In AddOne: ); int = ; rintf ( = %d\n, ); return ; = AddOne (); } rintf ( In main: ); rintf ( = %d\n, ); } 6 6 To πρόγραμμα εκτυπώνει: In AddOne: =6 In main: = 6 14-3 Συναρτήσεις Σήμερα θα δούμε σε περισσότερο βάθος τις συναρτήσεις. Α) Συναρτήσεις με Παραμέτρους Με Επιστροφή Πολλών Τιμών Β) Εισαγωγή στους δείκτες Γ) Η έννοια και η χρήση του * Δ) Αποσφαλμάτωση - έλεγχος 14-4
Χρήση δεικτών ΝΕΟΣ ΣΩΣΤΟΣ τρόπος να αυξήσουμε το κατά 1 #include <stdio.h> void AddOne (int*); void AddOne (int *) { main () * = *+1; { rintf ( In AddOne: ); int = ; rintf ( = %d\n, *); AddOne (&); } rintf ( In main: ); rintf ( = %d\n, ); } 6 6 To πρόγραμμα εκτυπώνει: In AddOne: =6 In main: = 6 14- int = ; AddOne (&); Διευθύνσεις ως παράμετροι είναι μία μεταβλητή τύπου int & είναι η διεύθυνσή του στη μνήμη 364347 14-6
Εισαγωγή στους δείκτες Συμβολίζονται με * Ένα μέρος της μνήμης του οποίου το περιεχόμενο είναι διεύθυνση μνήμης 364347 364347 To δείχνει δηλαδή στη μεταβλητή 14-7 Χρήση * στις τυπικές μεταβλητές void AddOne (int *) To είναι ένας δείκτης σε μεταβλητές τύπου int. O τύπος εξόδου παραμένει void AΛΛΑ, το int * είναι παράμετρος όχι μόνο εισόδου αλλά και εξόδου ΔΕΔΟΜΕΝΟΥ ότι η συνάρτηση γνωρίζει την διεύθυνση που είναι αποθηκευμένη η μεταβλητή, ώστε να αλλάξει την τιμή της. 14-
Χρήση * στο σώμα συναρτήσεων * = *+1; 364347 * 364347 Ερμηνεία: Ακολούθησε τον δείκτη και βρες την τιμή της μεταβλητής στην οποία δείχνει. : 364347 : * == 14-9 * : Ανακεφαλαίωση 3 χρήσεις/ερμηνείες: Πολλαπλασιασμός (δυαδικός τελεστής) 2 * a Τυπική Παράμετρος int * Σημαίνει «δείκτης σε» Μοναδιαίος (unary) τελεστής * = / Σημαίνει «ακολούθησε τον δείκτη» 14-10
scanf με δείκτες int ber; int *ber; scanf( %d %d, &ber, ber); ΠΡΟΣΟΧΗ: Δεν βάζουμε το σύμβολο & καθώς η μεταβλητή ber ήδη αναφέρεται σε διεύθυνση. 14-11 Παράδειγμα συνάρτησης που υπολογίζει πολλαπλές τιμές Δημιουργήστε μία συνάρτηση που διαχωρίζει έναν αριθμό σε ακέραιο και δεκαδικό μέρος void searate (double, int *int, double *frac) { *int = (int); *frac = (*int); } int main () { double value, fractional_art; int integer_art; searate(value, &integer_art, & fractional_art); rintf( The integer art of %.4f is %d and the fractional art is %.4f, value, integer_art, fractional_art); } 14-12
*=; *=; =; λάθος σωστό 14-13 *=; *=; *=*; σωστό λάθος 14-14
Έλεγχος προγράμματος με πολλές συναρτήσεις Ο έλεγχος πρέπει να αρχίσει πολύ πριν ολοκληρωθεί η ανάπτυξη όλων των συναρτήσεων. Χρήση σκελετών (stubs) Εκτυπώνουν προειδοποιητικά μηνύματα Εκτυπώνουν μηνύματα με τις τιμές εισόδου Δίνουν (ψεύτικες) τιμές στις παραμέτρου εξόδου 14-1 Π.χ., Σκελετός συνάρτησης που βρίσκει τον ΜΚΔ δύο ακεραίων int mkd(int a, int b) { rintf( WARNING: THIS FUNCTION IS INCOMPLETE! ) rintf( a= %d, b= %d, a,b); return a*b; } 14-16
Αποσφαλμάτωση Συμβουλές Σχόλια για κάθε συνάρτηση, τις παραμέτρους της και τις τοπικές μεταβλητές Εκτύπωση ενδείξεων για τη ροή του προγράμματος Όνομα συνάρτησης που καλείται Τιμή παραμέτρων κατά την κλίση Τιμή παραμέτρων εξόδου μετά την ολοκλήρωση 14-17