Μάθημα 7 - Υποπρογράμματα Εργαστήριο 11 Ο TO ΥΠΟΠΡΟΓΡΑΜΜΑ ΣΥΝΑΡΤΗΣΗ Βασικές Έννοιες: Υποπρόγραμμα, Ανάλυση προβλήματος, top down σχεδίαση, Συνάρτηση, Διαδικασία, Παράμετρος, Κλήση συνάρτησης, Μετάβαση της ροής εκτέλεσης, Επιστροφή από ένα υποπρόγραμμα ΑΠΑΙΤΟΥΜΕΝΗ ΥΛΗ Κεφάλαια 5 της PASCAL, Σ. Πανέτσος Σελίδες 121 133 11.1 Περιεχόμενα Στο προηγούμενο μάθημα εξετάσαμε τη λειτουργία του υποπρογράμματος σ ένα πρόγραμμα Αναλύσαμε πως το υποπρόγραμμα (η ιδέα του υποπρογράμματος) εμφανίζεται σαν αποτέλεσμα της ανάλυσης ενός προβλήματος σε επιμέρους προβλήματα, για την ευκολότερη λύση του αρχικού προβλήματος. Αναπτύξαμε τα πλεονεκτήματα της ανάπτυξης ενός προγράμματος μέσα από υποπρογράμματα και εξετάσαμε τη σύνδεση του προγράμματος με το υποπρόγραμμα, ή τα υποπρογράμματα, μέσα απ τη διαδικασία της κλήσης της συνάρτησης από το κυρίως πρόγραμμα και της επιστροφής ενός αποτελέσματος από το υποπρόγραμμα στο πρόγραμμα. 11.2 ΠΩΣ ΓΡΑΦΟΥΜΕ ΕΝΑ ΥΠΟΠΡΟΓΡΑΜΜΑ? Από τη στιγμή που έχουμε αναλύσει ένα πρόβλημα σε επιμέρους προβλήματα και έχουμε εντοπίσει / απομονώσει τα βασικά προβλήματα / διαδικασίες, ανάμεσα στα επιμέρους προβλήματα στα οποία έχουμε αναλύσει το αρχικό πρόβλημα, επιχειρούμε πρώτα να λύσουμε αυτά τα βασικά προβλήματα, γράφοντας ένα πρόγραμμα για καθένα από αυτά. Μετά συνδυάζουμε αυτά τα προγράμματα ως υποπρογράμματα σε ένα κυρίως πρόγραμμα, για τη λύση του αρχικού προβλήματος. Όμως, πως γράφουμε ένα υποπρόγραμμα? Όπως και το πρόγραμμα, το υποπρόγραμμα είναι ένας συνδυασμός από εντολές από τις ίδιες εντολές που γράφεται και ένα πρόγραμμα για λύση ενός συγκεκριμένου προβλήματος από τον υπολογιστή. Γι αυτό το λόγο, σε γενικές γραμμές, η διαδικασία που ακολουθούμε για να γράψουμε ένα υποπρόγραμμα είναι η ίδια με αυτή που ακολουθούμε για να γράψουμε ένα πρόγραμμα. 1
Πρώτα γράφουμε έναν αλγόριθμο για τη λύση αυτού του προβλήματος. Μετά επιχειρούμε να μετατρέψουμε αυτό τον αλγόριθμο σε ένα συνδυασμό από εντολές της PASCAL για τη λύση του προβλήματος από τον υπολογιστή. Όμως, αυτός ο συνδυασμός εντολών θα πρέπει να είναι στη μορφή ενός υποπρογράμματος. Βήμα 1: Αφού αναλύσουμε ένα πρόβλημα σε επιμέρους προβλήματα, γράφουμε το υποπρόγραμμα για κάθε επιμέρους πρόβλημα, όπως ακριβώς θα γράφαμε και ένα πρόγραμμα για αυτό το πρόβλημα, γράφοντας αρχικά έναν αλγόριθμο για τη λύση του συγκεκριμένου προβλήματος από τον υπολογιστή και μετατρέποντας αυτόν τον αλγόριθμο σε πρόγραμμα. Αφού γράψουμε τον αλγόριθμό τη λύση ενός προβλήματος από ένα υποπρόγραμμα, το επόμενο βήμα είναι να προσδιορίσουμε την ανταλλαγή δεδομένων, ανάμεσα στο υποπρόγραμμα και το κυρίως πρόγραμμα. Ένα υποπρόγραμμα περιέχεται και καλείται από το κυρίως πρόγραμμα για να λύσει ένα επιμέρους πρόβλημα. Λέμε ότι το κυρίως πρόγραμμα καλεί το υποπρόγραμμα για να λύσει ένα επιμέρους πρόβλημα. Επειδή το υποπρόγραμμα αποτελεί και λειτουργεί ως ανεξάρτητη οντότητα, κατά την εκτέλεση ενός προγράμματος, το κυρίως πρόγραμμα, όταν καλεί ένα υποπρόγραμμα για να λύσει ένα επιμέρους πρόβλημα πρέπει να μεταβιβάσει στο υποπρόγραμμα τα δεδομένα που χρειάζεται για να λύσει αυτό το επιμέρους πρόβλημα. Από τη πλευρά του το υποπρόγραμμα, μόλις ολοκληρώσει τον υπολογισμό του πρέπει να επιστρέψει, δηλαδή να μεταβιβάσει πίσω στο πρόγραμμα το αποτέλεσμα αυτού του υπολογισμού. Αυτή η επικοινωνία είναι βασική γιατί διατηρεί ανεξάρτητη τη λειτουργία του υποπρογράμματος από το πρόγραμμα. Η μεταβίβαση δεδομένων από το κυρίως πρόγραμμα προς το υποπρόγραμμα γίνεται μέσω των παραμέτρων του υποπρογράμματος. Η επιστροφή γίνεται μέσα από την εκχώρηση του αποτελέσματος στο όνομα της συνάρτησης. Βήμα 2: Έτσι, εφόσον έχουμε γράψει τον αλγόριθμο, το επόμενο βήμα είναι να ορίσουμε ποιο αποτέλεσμα θα επιστρέφει η συνάρτηση στο κυρίως πρόγραμμα. Εφόσον έχουμε ορίσει το αποτέλεσμα που υπολογίζει και επιστρέφει μία συνάρτηση στο κυρίως πρόγραμμα, το επόμενο βήμα είναι να ορίσουμε τα δεδομένα που χρειάζεται η συνάρτηση από το κυρίως πρόγραμμα προκειμένου αυτή να ολοκληρώσει τον υπολογισμό της. Βήμα 3: Oρίζουμε τα δεδομένα / τιμές που το κυρίως πρόγραμμα πρέπει να μεταβιβάσει στη συνάρτηση προκειμένου αυτή να λύσει το πρόβλημα που καλείται να λύσει. 2
Τα δεδομένα από το κυρίως πρόγραμμα προς τη συνάρτηση μεταβιβάζονται μέσω των παραμέτρων της συνάρτησης. Για κάθε δεόμενο που χρειάζεται η συνάρτηση από το κυρίως πρόγραμμα, ορίζουμε μία παράμετρο μια μεταβλητή που έχει το τύπο του συγκεκριμένου δεδομένου και που θα παριστάνει τη τιμή του κατά την εκτέλεση της συνάρτησης. Οι παράμετροι είναι ειδικές μεταβλητές οι οποίες παίρνουν τιμές κατά τη κλήση της συνάρτησης στο κυρίως πρόγραμμα. Οι παράμετροι είναι ορισμένες μόνο μέσα στο περιβάλλον της συνάρτησης και όσο κρατά η εκτέλεση του εντολών της συνάρτησης. Οι παράμετροι δεν μπορεί αλλάξουν τιμή κατά την εκτέλεση της συνάρτησης, δεν μπορεί δηλαδή να εμφανίζονται στα αριστερά μιας εκχώρησης. Αυτά τα βήματα ολοκληρώνουν το υποπρόγραμμα έχοντας ορίσει τις παραμέτρους του υποπρογράμματος, τη τιμή που αυτό επιστρέφει και έχοντας τον αλγόριθμο για τη λύση του προβλήματος που η συνάρτηση καλείται να λύσει, μπορούμε τώρα να γράψουμε το κώδικα της συνάρτησης. Εξετάζουμε αυτή τη διαδικασία μέσα από παραδείγματα και ασκήσεις. ΜΕΡΟΣ Β Εργαστηριακό Μέρος Άσκηση 1 Γράψτε ένα πρόγραμμα που να διαβάζει έναν ακέραιο αριθμό και να εμφανίζει στην οθόνη όλους τους διαιρέτες αυτού του αριθμού. Αλγόριθμος Βήμα 1: Διάβασε έναν αριθμό, α από την οθόνη Βήμα 2 Υπολογισμός των διαιρετών: Για να υπολογίσουμε τους διαιρέτες ενός αριθμού α, αυτούς δηλαδή τους αριθμούς που διαιρούν ακριβώς τον α, αφήνοντας υπόλοιπο 0, εξετάζουμε όλους τους αριθμούς: 2, 3, 4,, α / 2 Για κάθε ένα από τους παραπάνω αριθμούς, ελέγχουμε εάν αυτός διαιρεί ακριβώς τον α. Κάθε ένας από τους παραπάνω αριθμούς που διαιρεί ακριβώς τον α είναι διαιρέτης του και το πρόγραμμα πρέπει να τον εκτυπώσει στην οθόνη. Εξετάζοντας τον αλγόριθμο για τη λύση του προβλήματος από τον υπολογιστή, βλέπουμε ότι μία βασική διαδικασία στον υπολογισμό των διαιρετών ενός αριθμού είναι να εξετάσουμε εάν κάθε ένας από τους αριθμούς: 2, 3, 4,, α/2 3
είναι διαιρέτης του α. Για αυτό, γράφουμε ένα υποπρόγραμμα, μία συνάρτηση υποπρόγραμμα για να εκτελεί αυτόν τον υπολογισμό, να ελέγχει δηλαδή εάν ένας αριθμός διαιρεί ακριβώς ένα άλλο. Πώς γράφουμε αυτή τη συνάρτηση? Βήμα 1 πρόβλημα : Γράψτε μία συνάρτηση που να υπολογίζει εάν ένας αριθμός διαιρεί ακριβώς έναν άλλο. Για δύο οποιουσδήποτε ακέραιους αριθμούς a και b, ο a διαιρεί ακριβώς τον b εάν: b mod a = 0 εάν δηλαδή το υπόλοιπο της διαίρεσης του b δια a είναι 0. Άρα, μία συνάρτηση, προκειμένου να εξετάσει εάν ένας αριθμός a διαιρεί ακριβώς έναν άλλο αριθμό b, αρκεί να υπολογίσει το υπόλοιπο της διαίρεσης b δια a. Βήμα 2 επιστροφή: Η συνάρτηση πρέπει να υπολογίζει εάν ένας αριθμός a διαιρεί ακριβώς έναν άλλο αριθμό b. Παριστάνουμε την ισχύ αυτής της σχέσης με τη λογική τιμή TRUE και την άρνησή αυτής της σχέσης με τη λογική τιμή FALSE. Εάν δηλαδή, ο αριθμός a διαιρεί ακριβώς τον αριθμό b, τότε η συνάρτηση επιστρέφει στο κυρίως πρόγραμμα τη λογική τιμή TRUE. Διαφορετικά, η συνάρτηση επιστρέφει στο κυρίως πρόγραμμα τη λογική τιμή FALSE. Επειδή η συνάρτηση επιστρέφει το αποτέλεσμα του υπολογισμού της στο κυρίως πρόγραμμα, με τη λογική τιμή TRUE, ή τη λογική τιμή FALSE, λέμε ότι αυτή η συνάρτηση έχει το τύπο Boolean και την ορίζουμε όπως παρακάτω: function diairetis ( ) : boolean; Βήμα 3 παράμετροι: Μία συνάρτηση, για να υπολογίζει εάν ένας αριθμός a διαιρεί ακριβώς έναν άλλο αριθμό b, χρειάζεται να γνωρίζει τις τιμές των a και b. Επειδή η συνάρτηση χρειάζεται να γνωρίζει δύο δεδομένα για να εκτελέσει τον υπολογισμό της, ορίζουμε αυτά τα δεδομένα ως παραμέτρους της συνάρτησης: function diairetis (a, b : integer) : boolean; Οι τιμές των παραμέτρων a και b μεταβιβάζονται στη συνάρτηση από το κυρίως πρόγραμμα, κατά τη κλήση της συνάρτησης. Οι παράμετροι μίας συνάρτησης και η επιστροφή μίας τιμής από τη συνάρτηση στο κυρίως πρόγραμμα, μέσα από την εκχώρηση αυτής της τιμής στο όνομα της συνάρτησης αποτελούν το μηχανισμό που συνδέει τη συνάρτηση με το κυρίως πρόγραμμα (Εικόνα 1). 4
Βήμα 4: Έχοντας ορίσει τη τιμή που επιστρέφει η συνάρτηση, τις παραμέτρους της και έχοντας σχεδιάσει τη διαδικασία του υπολογισμού που εκτελεί, μπορούμε να γράψουμε το κώδικα της συνάρτησης: function diairetis (a, b : integer) : boolean; end; if ( b mod a = 0 ) then diairetis := true else diairetis := false; Βήμα 5 Ενσωμάτωση της συνάρτησης στο κυρίως πρόγραμμα: Μπορούμε τώρα να γράψουμε το κυρίως πρόγραμμα που περιέχει και χρησιμοποιεί τη παραπάνω συνάρτηση για να υπολογίζει τους διαιρέτες ενός αριθμού a. program diairetes_arithmou; var i, orio, a : integer; eleghos : boolean; 5
function diairetis (a, b : integer) : boolean; end; if ( b mod a = 0 ) then diairetis := true else diairetis := false; write( Δώσε έναν ακέραιο αριθμό: ); readln(a); orio := a div 2; writeln( Οι διαιρέτες αυτού του αριθμού είναι οι: ); for i := 2 to orio do eleghos := diairetis(i, a); If (eleghos = TRUE) then writeln(i) end (* for *) end. Άσκηση 2: Ένας ακέραιος αριθμός είναι τέλειος, εάν το άθροισμα των παραγόντων αυτού του αριθμού συμπεριλαμβανομένου του 1, αλλά όχι του αριθμού είναι ίσο με τον αριθμό. Για παράδειγμα, ο αριθμός 6 είναι τέλειος γιατί το άθροισμα των παραγόντων του: 1 + 2 + 3 = 6 Παρακάτω είναι μία συνάρτηση που να εξετάζει εάν ένας αριθμός είναι τέλειος. function teleios (a : integer) : boolean; var i, sum : integer; sum := 1; 6
for i := 2 to a do if ( a mod i = 0 ) then sum := sum + i; end; if sum = a then teleios := true else teleios := false; end; Χρησιμοποιήστε αυτή τη συνάρτηση σ ένα πρόγραμμα που καθορίζει και προβάλλει όλους τους τέλειους αριθμούς από το 1 έως το 1000. Άσκηση 3: Επαρκείς είναι οι ακέραιοι αριθμοί των οποίων το άθροισμα των διαιρετών είναι μεγαλύτερο από τον ίδιο τον ακέραιο. Ελλιπείς λέγονται οι ακέραιοι των οποίων το άθροισμα των διαιρετών είναι μικρότερο από τον ίδιο τον ακέραιο. Τροποποιείστε τη συνάρτηση teleios παραπάνω, γράφοντας δύο ακόμα συναρτήσεις τις eparkis και ellipis που υπολογίζουν εάν ένας ακέραιος είναι επαρκής, ή ελλιπής, αντίστοιχα. Χρησιμοποιείστε αυτές τις συναρτήσεις στο πρόγραμμα της άσκησης 2 για να υπολογίζει όλους τους τέλειους, επαρκείς και ελλιπείς ακέραιους αριθμούς από το 2 έως το 1000. 7
Μάθημα 7 - Υποπρογράμματα 8
ΕΡΓΑΣΤΗΡΙΟ 8 Εισαγωγή στο Προγραμματισμό με τη PASCAL & τη MATLAB ΣΥΝΑΡΤΗΣΕΙΣ Όνομα: 1. Η παρακάτω συνάρτηση στη PASCAL υπολογίζει εάν ένας αριθμός a διαιρείται ακριβώς από έναν άλλο: function diairetis (a, b : integer) : boolean; end; if ( b mod a = 0 ) then diairetis := true else diairetis := false; 2. Γράψτε μία συνάρτηση που να υπολογίζει τη n δύναμη ενός ακέραιου αριθμού κ, χρησιμοποιώντας τη παρακάτω συνάρτηση function power ( k, n : integer) : real; 1
Εργαστήριο 8 Συναρτήσεις 3. Χρησιμοποιείστε αυτή τη συνάρτηση σ ένα πρόγραμμα, για να υπολογίζει όλους τους διαιρέτες ενός αριθμού a. 2
4. Γράψτε ένα πρόγραμμα που να διαβάζει από την οθόνη το μήκος (l), τη διατομή (S) και το ρεύμα (I), σ ένα αγωγό (στο καλώδιο μίας ηλεκτρικής γραμμής). Το πρόγραμμα θα πρέπει να υπολογίζει την εσωτερική αντίσταση (R) και τη πτώση τάσης (ΔV), στον αγωγό, από τους τύπους, της εσωτερικής αντίστασης ενός αγωγού και της πτώσης τάσης. 3