Η τιµή εξόδου κάποιας συνάρτησης µπορεί να είναι δείκτης, π.χ.

Σχετικά έγγραφα
Δοκιμή και Αποσφαλμάτωση Testing and Debugging

Συναρτήσεις. Κατασκευαστικά Τεµάχια για τη ηµιουργία Αρθρωτών Προγραµµάτων

Επανάληψη. Εντολές while, for, do-while

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. Δείκτες (Διάλεξη 14)

Εισαγωγή στον Προγραμματισμό

Η βασική λειτουργία σε όλες αυτές τις συναρτήσεις είναι η εκτύπωση γραµµών.

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Κεφάλαιο 6: Συναρτήσεις IΙΙ Αρθρωτός Προγραμματισμός. (Διάλεξη 14) Παράδειγμα: Αλλαγή τιμής μεταβλητής μόνο τοπικά

Κεφάλαιο , 3.2: Συναρτήσεις II. (Διάλεξη 12)

Περαιτέρω για Συναρτήσεις

Προγραμματισμός Η/Υ (ΤΛ2007 )

Μεθόδων Επίλυσης Προβλημάτων

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

Προγραμματισμός Ι (ΗΥ120)

Ασκήσεις σε Επαναληπτικούς Βρόχους και Συναρτήσεις. Επανάληψη για την ενδιάμεση εξέταση. (Διάλεξη 13)

Δομημένος Προγραμματισμός (ΤΛ1006)

Ανάπτυξη και Σχεδίαση Λογισμικού

οµές Επιλογής Εντολές if και switch

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Προγραμματισμός Η/Υ (ΤΛ2007 )

Η γλώσσα προγραμματισμού C

Η βασική συνάρτηση προγράμματος main()

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Ηβασικήσυνάρτηση προγράμματος main()

Η Γλώσσα C Μία Σφαιρική Ανασκόπηση

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Η γλώσσα προγραμματισμού C

ΗΥ-150. Προγραµµατισµός. Εντολές Ελέγχου Ροής

Εισαγωγή στη γλώσσα προγραμματισμού C++

ΤΕΜ-101 Εισαγωγή στους Η/Υ Εξεταστική Ιανουαρίου 2011 Θέματα Β

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Να εκτυπωθούν οι πρώτες Ν σειρές του τριγώνου, χρησιµοποιώντας ένα πίνακα µεγέθους Ν στοιχείων (η Ν-οστή σειρά περιέχει Ν στοιχεία).

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΕΠΛ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΕΘΟΔΩΝ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 6 Ο. Συναρτήσεις Τοπικές, καθολικές, στατικές μεταβλητές Μεταβλητές τύπου extern και register Αναδρομή

12. Συναρτήσεις (Μέρος ΙI)

Προγραµµατιστικές Τεχνικές

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

ΕΠΛ 034: Εισαγωγήστον ΠρογραµµατισµόγιαΗΜΥ

Εισαγωγή στον Προγραμματισμό

Κεφάλαιο : Επαναλήψεις (for, do-while)

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 6/12/07

Δομημένος Προγραμματισμός

Προγραμματισμός Η/Υ (ΤΛ2007 )

Κεφάλαιο 3.1, : Συναρτήσεις I. (Διάλεξη 11)

Εισαγωγή στον Προγραμματισμό

Η γλώσσα προγραμματισμού C

Περιεχόμενα. Πρόλογος... 17

Εισαγωγή στον Προγραμματισμό

Προγραμματισμό για ΗΜΥ

Κεφάλαιο 4: Συνθήκες Έλεγχου (if-else, switch) και Λογικοί τελεστές / παραστάσεις. (Διάλεξη 8)

Περιεχόμενα. Πρόλογος... 21

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

Στόχοι και αντικείμενο ενότητας. Εκφράσεις. Η έννοια του τελεστή. #2.. Εισαγωγή στη C (Μέρος Δεύτερο) Η έννοια του Τελεστή

Ανάπτυξη και Σχεδίαση Λογισμικού

Κεφάλαιο : Επαναλήψεις (oι βρόγχοιfor, do-while) (Διάλεξη 10) Εντολές Επανάληψης που θα καλυφθούν σήμερα

ΕΠΛ131 Αρχές Προγραμματισμού

ΕΡΓΑΣΤΗΡΙΑΚΕΣ ΑΣΚΗΣΕΙΣ C ΣΕΙΡΑ 2 η

ΣΥΝΑΡΤΗΣΕΙΣ (Functions)

ΣΧΕΔΙΑΣΗ ΚΑΙ ΥΛΟΠΟΙΗΣΗ ΛΟΓΙΣΜΙΚΟΥ

Προγραμματισμό για ΗΜΥ

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Η γλώσσα προγραμματισμού Strange

Συναρτήσεις και διαδικασίες

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ & ΥΠΟΛΟΓΙΣΤΙΚΗ ΦΥΣΙΚΗ

Προγραμματισμός Η/Υ (ΤΛ2007 )

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (Programming in the large)

Μεθόδων Επίλυσης Προβλημάτων

Προγραμματισμός Ι. Θεματική ενότητα 4: Έλεγχος ροής Προτάσεις υπό συνθήκη διακλάδωσης

Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: ΕΠΛ 131 Αρχές Προγραµµατισµού I 3-2

Επανάληψη για τις Τελικές εξετάσεις

Η γλώσσα προγραμματισμού C

Μεταγλωττιστές. Εργαστήριο 5. Εισαγωγή στο BISON. Γεννήτρια Συντακτικών Αναλυτών. 2 η Φάση Μεταγλώττισης Συντακτική Ανάλυση

Μεθόδων Επίλυσης Προβλημάτων

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

Προγραμματισμός Ι (ΗΥ120)

Δομημένος Προγραμματισμός (ΤΛ1006)

Εισαγωγή στον Προγραμματισμό (με. τη C)

Κεφάλαιο 3.1, : Συναρτήσεις I. ( ιάλεξη 11) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 3 η : Επίλυση Προβληµάτων Χειµερινό Εξάµηνο 2011

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Επανάληψη για τις Τελικές εξετάσεις. (Διάλεξη 24) ΕΠΛ 032: ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΕΘΟΔΩΝ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

ΕΡΓΑΣΤΗΡΙΟ 6: Συναρτήσεις και Αναδρομή

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #2

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Προγραμματισμός Η/Υ. Ενότητα 7: Συναρτήσεις

Προγραμματισμός Ι. Προεπεξεργαστής. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Εισαγωγή στην γλώσσα προγραμματισμού C

Υπολογισμός - Εντολές Επανάληψης

Πίνακες. Οι πίνακες αποτελούν ένα σηµαντικό δοµηµένο τύπο δεδοµένων (structured data type) ή πιο απλά µία δοµή δεδοµένων (data structure).

ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

ΕΡΓΑΣΤΗΡΙΟ 4: Μεταβλητές, Δομές Ελέγχου και Επανάληψης

Εισαγωγή στον Προγραμματισμό

Σε γενικές γραμμές, είναι καλή πρακτική να γράϕουμε προγράμματα C που αποτελούνται από πολλές και μικρές συναρτήσεις, παρά από λίγες και μεγάλες.

ΕΠΛ 032.3: Προγραµµατισµός ΜεθόδωνΕπίλυσηςΠροβληµάτων

Transcript:

είκτες ως Τιµές Εξόδου Η τιµή εξόδου κάποιας συνάρτησης µπορεί να είναι δείκτης, π.χ. int *select (int f (int, int), int *add1, int *add2) { if (f (*add1, *add2)) return add1; else return add2; Η συνάρτηση select λαµβάνει, ως πρώτη παράµετρο, µία δυαδική συνάρτηση-κατηγόρηµα, f, και ως δεύτερη και τρίτη παράµετρο, δύο διευθύνσεις ακεραίων, add1 και add2. Εφαρµόζει το κατηγόρηµα f στο περιεχόµενο της διεύθυνσης add1, ως πρώτο όρισµα, και το περιεχόµενο της διεύθυνσης add2, ως δεύτερο όρισµα. Εάν η τιµή αλήθειας από αυτή την αποτίµηση είναι true η συνάρτηση select επιστρέφει τη διεύθυνση add1, διαφορετικά επιστρέφει τη διεύθυνση add2. Πρόβληµα: Εισδοχή τριών ακεραίων, και επιλογή του µεγαλύτερου ανάµεσά τους. Η επεξεργασία να κάνει χρήση µόνο δύο µεταβλητών. 29

/* Ο ακόλουθος ορισµός δεν είναι επιτρεπτός επειδή κάνει χρήση τριών µεταβλητών */ void main () { int num1, num2, num3; printf( \nenter 3 integers: ); scanf( %d%d%d, &num1, &num2, &num3); if (num1 > num2 && num1 > num3) printf( \nthe biggest number is %d, num1); else if (num2 > num1 && num2 > num3) printf( \nthe biggest number is %d, num2); else printf( \nthe biggest number is %d, num3); /* Επιτρεπτός ορισµός */ void main () { int num1, num2; printf( \nenter 3 integers: ); scanf( %d%d, &num1, &num2); if (num1 > num2) scanf( %d, &num2); else scanf( %d, &num1); if (num1 > num2) printf( \nthe biggest number is %d, num1); else printf( \nthe biggest number is %d, num2); 30

/* Ορισµός µε τη χρήση της select */ int lessp (int x, int y) {return x < y ; int greaterp (int x, int y) {return x > y ; void main () { int num1, num2; printf( \nenter 3 integers: ); scanf( %d%d, &num1, &num2); scanf( %d, select(lessp, &num1, &num2)); printf( \nthe biggest number is %d, *select(greatep, &num1, &num2)); Ανάλυση των Κλήσεων της select Η πρώτη κλήση της select έχει ως πρώτο όρισµα τη συνάρτηση-κατηγόρηµα lessp, και ως δεύτερο και τρίτο όρισµα τις διευθύνσεις των µεταβλητών num1 και num2. H select καλείται για να επιλέξει την µεταβλητή µε την µικρότερη τιµή. Η διεύθυνση αυτής της µεταβλητής αποτελεί την τιµή εξόδου της κλήσης της select. Αυτή η διεύθυνση διοχετεύεται ως όρισµα στην scanf. 31

Το αποτέλεσµα είναι ότι ο µικρότερος ανάµεσα στους αρχικούς δύο αριθµούς, αντικαθιστάται από τον τρίτο αριθµό. lessp... &num1 select &num2 scanf Η δεύτερη κλήση της select έχει ως πρώτο όρισµα τη συνάρτηση-κατηγόρηµα greaterp. Το δεύτερο και τρίτο όρισµα είναι, όπως και για την πρώτη κλήση, οι διευθύνσεις των µεταβλητών num1 και num2. Εδώ η select καλείται για να επιλέξει την µεταβλητή µε τη µεγαλύτερη τιµή. Η διεύθυνση αυτής της µεταβλητής αποτελεί την τιµή εξόδου της κλήσης της select. Αυτή η διεύθυνση διοχετεύεται στον µοναδιαίο τελεστή *, προς ανάκτηση του περιεχοµένου της, το οποίο στη συνέχεια διοχετεύεται ως όρισµα στην printf. greaterp... &num1 select * &num2 printf Σηµείωση: Ονοµασίες που λήγουν σε p υποδηλώνουν κατηγόρηµα (predicate) ή δείκτη (pointer). 32

Εµβέλεια Ονοµασιών Η εµβέλεια µίας ονοµασίας (scope of a name) είναι ο χώρος του προγράµµατος όπου δεδοµένη ερµηνεία της ονοµασίας είναι ορατή, ή µπορεί να γίνει αναφορά σε αυτή. Ονοµασίες των οποίων η εµβέλεια είναι ολόκληρο το πρόγραµµα είναι καθολικές (global). ιαφορετικά είναι τοπικές (local). εν επιτρέπεται να υπάρχει επικάλυψη ανάµεσα στις εµβέλειες διαφορετικών ερµηνειών της ίδιας ονοµασίας, για τον απλό λόγο ότι δεν θα µπορούν να διαχωριστούν οι ερµηνείες της ονοµασίας στον επικαλυπτόµενο χώρο του προγράµµατος. 33

Παράδειγµα Σκελετικού Προγράµµατος #define MAX 950 #define LIMIT 200 /* πρωτότυπο συνάρτησης one */ void one (int anarg, double second); /* πρωτότυπο συνάρτησης fun_two */ int fun_two (int one, char anarg); void main () { int localvar; void one (int anarg, double second) { int onelocal; int fun_two (int one, char anarg) { int localvar; 34

Πρόγραµµα ΜΑΧ LIMIT one (1) anarg (1), second onelocal fun_two one (2), anarg (2) localvar (1) main localvar (2) 35

Οι ονοµασίες MAX, LIMIT, second, onelocal, fun_two και main, έχουν µόνο µία ερµηνεία. Οι ονοµασίες one, anarg και localvar, έχουν δύο ερµηνείες η κάθε µία. Ανάλυση ερµηνειών και εµβέλειων Καθολικές Σταθερές Οι σταθερές που δηλώνονται διαµέσου εντολών προς τον προεπεξεργαστή, π.χ. MAX και LIMIT, θα πρέπει να είναι καθολικές, η εµβέλειά τους δηλαδή θα πρέπει να είναι ολόκληρο το πρόγραµµα. Η ίδια ονοµασία δεν πρέπει να δηλώνεται σε άλλο σηµείο του προγράµµατος. Έτσι αυτές οι ονοµασίες έχουν µόνο µία ερµηνεία. Αυτό εξάλλου συνάδει και µε τη σηµασιολογία τους, ότι δηλαδή κάθε αναφορά σε µία από αυτές τις ονοµασίες αντικαθιστάται από την σχετική τιµή, πριν τη µεταγλώττιση του προγράµµατος. Οι πιο κάτω δηλώσεις δεν είναι επιτρεπτές #define Max 56 int some_fn (double Max); 36

Εποµένως οι ονοµασίες MAX και LIMIT έχουν µόνο µία ερµηνεία, η εµβέλεια της οποίας είναι ολόκληρο το πρόγραµµα. Ονοµασίες Συναρτήσεων, Παραµέτρων και Μεταβλητών Η ονοµασία one έχει δύο ερµηνείες: Ως συνάρτηση, one (1) Ως τυπική παράµετρος, τύπου int, της συνάρτησης fun_two, one (2) H εµβέλεια της one (1) είναι ο εαυτός της και η συνάρτηση main. Μόνο σε αυτούς τους χώρους του προγράµµατος είναι ορατή η ονοµασία one, µε την ερµηνεία της συνάρτησης. Εποµένως η συνάρτηση one (1) µπορεί να κληθεί από τον εαυτό της και την main. Η συνάρτηση fun_two δεν ανήκει στην εµβέλεια της one (1), διότι στο πλαίσιο της fun_two δεν θα µπορούσε να διαχωριστεί η one (1) από την one (2). Για αυτό το λόγο, η one (1) δεν µπορεί να κληθεί από την fun_two. Η εµβέλεια της one (2) είναι µόνο η συνάρτηση fun_two. Γενικά τυπικές παράµετροι είναι ορατές µόνο στις συναρτήσεις που τις ορίζουν. 37

Η ονοµασία second έχει µόνο µία ερµηνεία, ως τυπική παράµετρος τύπου double της one (1). Η εµβέλειά της είναι ο χώρος της one (1). Εποµένως είναι µία τοπική ονοµασία. Γενικά ονοµασίες των οποίων η εµβέλεια είναι µόνο µία συνάρτηση είναι τοπικές ονοµασίες. Τυπικές παράµετροι είναι τοπικές ονοµασίες. Το ίδιο και µεταβλητές που δηλώνονται στο πλαίσιο µίας συνάρτησης. Οι ακόλουθες δηλώσεις δεν είναι επιτρεπτές: int one (int x); int fn (int x) {int x = one(2);.... int fn2 (int one) {int two = one(3);... Η ονοµασία onelocal έχει µόνο µία ερµηνεία, ως πραγµατικός αριθµός, µε εµβέλεια τη συνάρτηση one (1). Η ονοµασία anarg έχει δύο ερµηνείες: Ως τυπική παράµετρος τύπου int της one (1), anarg (1) Ως τυπική παράµετρος τύπου char της fun_two, anarg (2) Η εµβέλεια της anarg (1) είναι η one (1) και της anarg (2) είναι η fun_two. 38

Η ονοµασία localvar έχει δύο ερµηνείες: Ως int, localvar (1) Πάλι ως int, localvar (2) Η εµβέλεια της localvar (1) είναι η συνάρτηση fun_two και της localvar (2) η main. Η ονοµασία fun_two έχει µόνο µία ερµηνεία, ως συνάρτηση. Η εµβέλειά της είναι ολόκληρο το πρόγραµµα, δηλαδή οι one (1), fun_two και main. Με άλλα λόγια η fun_two µπορεί να κληθεί από την one (1), τον εαυτό της και την main. Εποµένως η fun_two µπορεί να κληθεί από την one (1), παρόλο που η one (1) δεν µπορεί να κληθεί από την fun_two. Παροµοίως η ονοµασία main έχει µόνο µία ερµηνεία, ως συνάρτηση, η εµβέλεια της οποίας είναι ολόκληρο το πρόγραµµα. Εποµένως η main µπορεί να κληθεί από την one (1), την fun_two και τον εαυτό της. Παρόλο που είναι επιτρεπτό, κανονικά δεν θα πρέπει να υπάρχουν άλλες ερµηνείες της ονοµασίας main, λόγω της σηµασιολογίας της συνάρτησης main, π.χ. int fn (double main); void main () {. Η main µπορεί να καλέσει την fn, αλλά όχι αντιστρόφως. 39

Σύνοψη Ονοµασία Ορατή στην one Ορατή στην fun_two Ορατή στην main MAX LIMIT main localvar (στη main) one (η συνάρτηση) anarg (int) second onelocal fun_two one (τυπική παράµετρος) anarg (char) localvar (στη fun_two) Γενικοί Κανόνες Η εµβέλεια µίας συνάρτησης αρχίζει από το πρωτότυπό της και καλύπτει το υπόλοιπο του προγράµµατος. Σε αυτή την εµβέλεια δεν περιλαµβάνονται συναρτήσεις οι οποίες διατυπώνουν διαφορετικές ερµηνείες σε αυτή την ονοµασία. Τυπικές παράµετροι και τοπικές µεταβλητές είναι ορατές µόνο στη συνάρτηση που ανήκουν. Ονοµασίες που αντιστοιχούν σε καθολικές σταθερές δεν πρέπει να έχουν άλλη ερµηνεία από αυτή. 40

ιάρκεια Ζωής Μεταβλητών Η διάρκεια ζωής µίας καθολικής µεταβλητής είναι η διάρκεια ζωής του προγράµµατος. Η διάρκεια ζωής µίας τοπικής µεταβλητής είναι η διάρκεια ζωής της κλήσης της συνάρτησης στην οποία ανήκει, εκτός εάν έχει δηλωθεί ως static, οπόταν η διάρκεια ζωής της είναι η διάρκεια ζωής του προγράµµατος. 41

οκιµή και Αποσφαλµάτωση Testing and Debugging Ο µεταγλωττιστής εντοπίζει τα συντακτικά λάθη ενός προγράµµατος. εν είναι όµως σε θέση να εντοπίσει λάθη στη λογική του προγράµµατος. δεδοµένα πρόγραµµα αποτέλεσµα Όταν το αποτέλεσµα δεν είναι το αναµενόµενο, βάσει των συγκεκριµένων δεδοµένων, το πρόγραµµα έχει λογικά λάθη. Αποσφαλµάτωση είναι η εντόπιση και διόρθωση λογικών λαθών. Προς αυτό το σκοπό µπορεί να χρησιµοποιηθούν τυχόν εργαλεία (debugging tools) τα οποία παρέχονται από το περιβάλλο προγραµµατισµού. οκιµή είναι ο έλεγχος του κατά πόσον το πρόγραµµα λειτουργεί σύµφωνα µε τις προδιαγραφές του. Η δοκιµή εµπλέπει αποσφαλµάτωση. 42

Στάδια οκιµής: Σχεδιασµός Περιπτώσεων: δεδοµένα αναµενόµενο αποτέλεσµα Εκτέλεση Περιπτώσεων: αναµενόµενο αποτέλεσµα? πραγµατικό αποτέλεσµα Για να είναι η δοκιµή ενός προγράµµατος ολοκληρωµένη, οι περιπτώσεις δοκιµής πρέπει να καλύπτουν ολόκληρο το φάσµα των πραγµατικών περιπτώσεων. Ακόµη και για απλά προγράµµατα η δοκιµή είναι περίπλοκη διαδικασία, η οποία χρειάζεται να γίνει µε οργανωµένο και µεθοδικό τρόπο. Μόνο έτσι θα είναι ολοκληρωµένη και αποδοτική στην ανακάλυψη των λογικών λαθών. Αρθρωτά προγράµµατα, αποτελούµενα από ένα αριθµό απλούστερων µονάδων, ευκολύνουν τις διαδικασίες της δοκιµής και αποσφαλµάτωσης. Ο προγραµµατιστής, διαµέσου της εµπειρίας του, αποκτά τις δικές του τεχνικές δοκιµής και αποσφαλµάτωσης. 43

Στρατηγικές για οκιµή Ολοκλήρωσε τον κώδικα για ολόκληρο το πρόγραµµα και µετά δοκίµασε. Πολύ κακή στρατηγική, αλλά η µόνη δυνατή σε σχέση µε µονολιθικά προγράµµατα (προγράµµατα χωρίς καθόλου άρθρωση). δεδοµένα λάθος αποτέλεσµα? δεδοµένα λάθος αποτέλεσµα? Ένα αρθρωτό πρόγραµµα ευκολύνει την εφαρµογή αυτής της στρατηγικής. Όµως η εντόπιση της συνάρτησης που είναι υπεύθυνη για το λάθος και η εξακρίβωση της αιτίας του λάθους, δεν είναι απαραίτητα κάτι το εύκολο. οκιµή Προσαυξήσεων Incremental Testing Αυτές οι στρατηγικές µπορούν να εφαρµοστούν µόνο σε αρθρωτά προγράµµατα, αφού η λογική που τις διέπει είναι η σταδιακή, µονάδα προς µονάδα, δοκιµή του προγράµµατος. 44

Στρατηγικές οκιµής Προσαυξήσεων ιεραρχική διάταξη µονάδων (συναρτήσεων) του προγράµµατος Α η συνάρτηση Α καλεί τη συνάρτηση Β Β Από πάνω προς τα κάτω (top-down) Από κάτω προς τα πάνω (bottom-up) Μείγµα (mixed strategies) Κοινός Στόχος: οκίµασε και αποσφαλµάτωσε ολοκληρωτικά κάθε µονάδα (συνάρτηση) του προγράµµατος, ξεχωριστά. Όταν δοκιµάζετε µία µονάδα, όλες οι υπόλοιπες µονάδες τις οποίες χρησιµοποιεί και εποµένως η δική της ορθή λειτουργία εξαρτάται από την ορθή λειτουργία αυτών, είτε έχουν ήδη 45

ελεγχθεί (στρατηγική από κάτω προς τα πάνω ), είτε αντιπροσωπεύονται από stubs (βλέπετε παρακάτω στρατηγική από πάνω προς τα κάτω ). Με αυτό το µεθοδικό τρόπο ελέγχου δεν παραγνωρίζεται καµµία µονάδα του προγράµµατος. Σε κάθε στάδιο της διεργασίας ο έλεγχος επικεντρώνεται σε µόνο µία µονάδα. Εποµένως εάν σε κάποια περίπτωση δοκιµής το πραγµατικό αποτέλεσµα δεν είναι το αναµενόµενο, η ένοχος µονάδα είναι η συγκεκριµένη. δεδοµένα Σ λάθος αποτέλεσµα 46

οκιµή Συνάρτησης Σ Περιπτώσεις Π 1 : δ 1 α 1 Π 2 : δ 2 α 2...... Π n : δ n α n α 1 α 2... α n......... Σ α i α i α j α j..... γιατί; Αποσφαλµάτωση της Σ Έστω Σ 1 Σ 1 Σ 2 Σ 2 Σ 4 Σ 3 Σ 3 Ιεραρχική διάταξη Σ 4 η Σ 1 καλεί τη Σ 2, η Σ 2 Συναρτήσεων καλεί τη Σ 3, κτλ 47

οκιµή από κάτω προς τα πάνω Πρώτα δοκιµάζεται η Σ 4 Μετά δοκιµάζεται η Σ 3 Μετά δοκιµάζεται η Σ 2 Τέλος δοκιµάζεται η Σ 1 Η Σ 4 δεν εξαρτάται από άλλη συνάρτηση. Η Σ 3 εξαρτάται από τη Σ 4. Η Σ 2 εξαρτάται από τη Σ 3 και κατ επέκταση από τη Σ 4. Η Σ 1 εξαρτάται από τη Σ 2, Σ 3 και Σ 4. Για την εφαρµογή αυτής της στρατηγικής χρειάζεται η χρήση των λεγόµενων test harness κώδικας για τη δοκιµή άλλου κώδικα. Η συνάρτηση main, η δοκιµή της οποίας θα γίνει στο τέλος, µπορεί διαδοχικά να αποτελεί το test harness για τη δοκιµή της κάθε µίας εκ των υπολοίπων συναρτήσεων. οκιµή από πάνω προς τα κάτω Πρώτα δοκιµάζεται η Σ 1 Μετά δοκιµάζεται η Σ 2 Μετά δοκιµάζεται η Σ 3 Τέλος δοκιµάζεται η Σ 4 Για τη δοκιµή της Σ 1 χρησιµοποιούνται stubs για τις Σ 2, Σ 3 και Σ 4. 48

Για τη δοκιµή της Σ 2 χρησιµοποιείται stub για τη Σ 3. Για τη δοκιµή της Σ 3 χρησιµοποιείται stub για τη Σ 4. Stub Μία άδεια συνάρτηση, η οποία δεν υπολογίζει τίποτα. Απλά δίνει το ορθό αποτέλεσµα στα συγκεκριµένα συµφραζόµενα. Αρχικά όλες οι συναρτήσεις είναι stubs και σταδιακά αντικαθιστώνται από τον πραγµατικό κώδικα, π.χ. το stub για κάποια συνάρτηση-κατηγόρηµα απλώς επιστρέφει τις κυριολεκτικές τιµές TRUE (1) ή FALSE (0): #define TRUE 1 #define FALSE 0 int is_leap (int year) {return TRUE; Σχεδίαση και οκιµή Κώδικα Η στρατηγική από πάνω προς τα κάτω συνήθως αποτελεί τον πιο φυσικό τρόπο ως προς τη σχεδίαση του προγράµµατος. Η στρατηγική από κάτω προς τα πάνω συνήθως αποτελεί τον πιο φυσικό τρόπο ως προς τη δοκιµή του προγράµµατος 49

Ίχνος Προγράµµατος Program Trace ίνει τη σειρά ενεργοποίησης των διαφόρων συναρτήσεων που αποτελούν το πρόγραµµα για δεδοµένη εκτέλεση του προγράµµατος. Επιπλέον το ίχνος µπορεί να δίνει τις εισόδους και εξόδους των εν λόγω κλήσεων των συναρτήσεων, καθώς επίσης τις τιµές σηµαντικών µεταβλητών. Το ίχνος παρέχει πολύ χρήσιµες πληροφορίες σχετικά µε την εκτέλεση του προγράµµατος οι οποίες µπορεί να βοηθήσουν στην ανίχνευση λογικών λαθών, όπως βρόχους άπειρης διάρκειας. Παράδειγµα #include <stdio.h> int factorial (int x); void main () { int n; printf( \ngive number: ); scanf( %d, &n); printf( \nfactorial %d = %d\n, n, factorial(n)); int factorial (int x) { if (x == 0) return 1; else return x * factorial(x 1); 50

$ fact Give number: 4 Factorial 4 = 24 Εκτέλεση µε ίχνος $ fact Give number: 4 Entry factorial < 4 Entry factorial < 3 Entry factorial < 2 Entry factorial < 1 Entry factorial < 0 Factorial 4 = 24 Το πιο πάνω ίχνος παρέχεται απλά µε την προσθήκη µίας κλήσης της εντολής printf στον ορισµό της factorial. int factorial (int x) { printf( \nentry factorial < %d, x); if (x == 0) return 1; else return x * factorial(x 1); Ίχνος µε πληροφορίες εισόδου και εξόδου Give number: 4 1: Entry factorial < 4 2: Entry factorial < 3 3: Entry factorial < 2 4: Entry factorial < 1 5: Entry factorial < 0 5: Exit factorial > 1 4: Exit factorial > 1 3: Exit factorial > 2 2: Exit factorial > 6 1: Exit factorial > 24 Factorial 4 = 24 51

Βοηθητικές Συναρτήσεις #define Indent 3 int Level = 0; void spaces (int n) { int s; for (s = 1; s <= n; s++) putchar( ); void Entry (char *f_name) { Level++; putchar( \n ); spaces(indent * Level); printf( %d: Entry %s <, Level, f_name); void Exit (char *f_name) { putchar( \n ); spaces(indent * Level); printf( %d: Exit %s >, Level, f_name); Level ; Επαναδιατύπωση factorial int factorial (int x) { int res; Entry( factorial ); printf( %d, x); if (x == 0) res = 1; else res = x * factorial (x 1); Exit( factorial ); printf( %d, res); return res; Comment: 52

Έστω ο ακόλουθος λανθασµένος ορισµός int factorial (int x) { int res; Entry( factorial ); printf( %d, x); if (x == 0) res = 1; else res = x * factorial (x + 1); Exit( factorial ); printf( %d, res); return res; Comment: $ fact Give number: 4 1: Entry factorial < 4 2: Entry factorial < 5 3: Entry factorial < 6 4: Entry factorial < 7 5: Entry factorial < 8 6: Entry factorial < 9....... Βρόχος άπειρης διάρκειας. Παράδειγµα #include <stdio.h> #define Indent = 3 int Level = 0; void spaces (int s) {... void Entry (char *f_name) { void Exit (char *f_name) { double abs (double x) {... 53

int good_enough (double x, double y) { const double eps = 0.00001; int res = abs(x y * y) <= eps; Entry( good_enough ); printf( %f, y); Exit( good_enough ); if (res) printf( TRUE); else printf( FALSE ); return res; double next_approx (double x, double y) { double res = (y + x / y) / 2.0; Entry( next_approx ); printf( %f, y); Exit( next_approx ); printf( %f,res); return res; double sqrt (double x) { double y = x; Entry( sqrt ); printf( %f, x); while (! good_enough(x,y)) y = next_approx(x,y); Exit( sqrt ); printf( %f,y); return y; void main () { double x; printf( \ngive number: ); scanf( %lf, &x); printf( \n The square root of %f is %f \n, x, sqrt(x)); 54

Ίχνος Προγράµµατος Give number: 2.0 1: Entry sqrt < 2.000000 2: Entry good_enough < 2.000000 2: Exit good_enough > FALSE 2: Entry next_approx < 2.000000 2: Exit next_approx > 1.500000 2: Entry good_enough < 1.50000 2: Exit good_enough > FALSE 2: Entry next_approx < 1.500000 2: Exit next_approx > 1.416667 2: Entry good_enough < 1.416667 2: Exit good_enough > FALSE 2: Entry next_approx < 1.416667 2: Exit next_approx > 1.414216 2: Entry good_enough < 1.414216 2: Exit good_enough > TRUE 1: Exit sqrt > 1.414216 The square root of 2.000000 is 1.414216 Απενεργοποίηση ίχνους #define TRACE 1 int factorial (int x) { int res; if (TRACE) {Entry( factorial ); printf( %d, x); if (x == 0) res = 1; else res = x * factorial (x + 1); if (TRACE) {Exit( factorial ); printf( %d, res); return res; Comment: 55

56