Η Γλώσσα Pascal Υποπρογράμματα Κεφάλαιο 11 © Βελώνης Γεώργιος
Εισαγωγή Πολλά προβλήματα, που επεξεργάζονται από υπολογιστές, είναι τόσο μεγάλα, που είναι αδύνατον για κάποιον να σχεδιάσει απ’ ευθείας αλγόριθμους που τα επιλύουν. Έτσι χρειάζεται να διασπαστούν σε υποπροβλήματα, που μπορούν να επεξεργαστούν χωριστά. Στη συνέχεια οι μερικοί αυτοί αλγόριθμοι συνδέονται και δίνουν τη λύση. Ο δομημένος προγραμματισμός στηρίζεται στην «αποκέντρωση» των εργασιών ενός προγράμματος. Κάθε συγκεκριμένη εργασία γίνεται μέσα από ένα είδος ανεξάρτητου υποπρογράμματος, στο εσωτερικό του οποίου μπορούν να γίνουν αλλαγές χωρίς να επηρεάζονται τα άλλα μέρη του προγράμματος.
Εισαγωγή Υπάρχουν δύο τύποι τέτοιων υποπρογραμμάτων, που ονομάζονται ρουτίνες ή διαδικασίες (Procedures) και συναρτήσεις (Functions). Κάθε διαδικασία ή συνάρτηση αποτελεί ένα αυτόνομο τμήμα του προγράμματος, που μπορεί να κληθεί από το κυρίως πρόγραμμα ή από κάποια άλλη διαδικασία ή συνάρτηση (ή και από τον εαυτό της), δέχεται κάποιες παραμέτρους και παράγει κάποια αποτελέσματα.
Εισαγωγή Η σχεδόν μοναδική διαφορά μεταξύ διαδικασίας και συνάρτησης είναι στον τρόπο σύνταξης: Η σύνταξη του ονόματος μιας ρουτίνας ισοδυναμεί με τη σύνταξη μιας εντολής της Turbo Pascal. Η σύνταξη του ονόματος μιας συνάρτησης ισοδυναμεί με τη σύνταξη μιας σταθεράς (δηλαδή μπορεί να συμμετέχει σε εκφράσεις για την εκτέλεση υπολογισμών ή να βρίσκεται μετά από το σύμβολο “:=”). Οι συναρτήσεις επιστρέφουν μία τιμή συνάρτησης όταν καλούνται.
Εισαγωγή Στην Pascal γενικά ισχύει ότι δε μπορεί κανείς να χρησιμοποιήσει ένα όνομα, πριν το δηλώσει. Βάσει αυτού του κανόνα, αν ένα υποπρόγραμμα Α καλείται από ένα υποπρόγραμμα Β, πρέπει το Α να υπάρχει πριν το Β, στο τμήμα δηλώσεων υποπρογραμμάτων. Το πρόβλημα αυτό μπορεί να λυθεί με τη χρήση του standard ονόματος Forward, που συνοδεύει την εντολή Procedure (ή Function) και το όνομά της, μαζί με τις παραμέτρους (και τον τύπο αν είναι συνάρτηση) της διαδικασίας (ή συνάρτησης), η οποία καλείται πριν από τον ορισμό της.
Εισαγωγή Το Forward καλείται directive. Ένα directive έχει σαν σκοπό να δώσει στον compiler τις πληροφορίες που χρειάζεται κατά το compilation.
Δήλωση Συναρτήσεων Η δήλωση μια συνάρτησης έχει την παρακάτω μορφή: Function όνομα_συνάρτησης(τυπικοί_παράμετροι): τύπος; {Επικεφαλίδα συνάρτησης} {Εδώ γράφονται οι τοπικές δηλώσεις της συνάρτησης, αν υπάρχουν, και μπορεί να είναι: Label, Const, Type, Var και δηλώσεις άλλων υποπρογραμμάτων που καλεί η συνάρτηση} Begin {Εδώ γράφονται οι εντολές, που είναι απαραίτητες για τον υπολογισμό της συνάρτησης. Πρέπει να υπάρχει τουλάχιστον μία εντολή, όπου το όνομα-συνάρτησης παίρνει τιμή} End;
Κανόνες Συναρτήσεων Η τιμή της συνάρτησης, που υπολογίζεται βάσει των δηλώσεων, θα είναι απλού τύπου ή τύπου pointer. Στην επικεφαλίδα συνάρτησης, μέσα στην παρένθεση δίνονται τα ονόματα των τυπικών (formal) παραμέτρων. Εδώ ορίζεται και ο τύπος των παραμέτρων. Αν μια συνάρτηση δεν έχει παραμέτρους παραλείπεται η παρένθεση. Function όνομα_συνάρτησης : τύπος;
Κανόνες Συναρτήσεων Στο τμήμα δηλώσεων της συνάρτησης μπορεί κανείς να δηλώσει π.χ. νέους τύπους και νέες μεταβλητές. Τα ονόματα που δηλώνει κανείς, μπορούν να χρησιμοποιηθούν μόνο από τη συνάρτηση. Οι μεταβλητές αυτές λέγονται τοπικές.
Κανόνες Συναρτήσεων Στις εντολές μεταξύ του Begin και του End μπορεί κανείς να εκμεταλλευτεί τις τυπικές παραμέτρους και τα μεγέθη που δηλώθηκαν στο τμήμα δηλώσεων της συνάρτησης. Επίσης μπορούν να χρησιμοποιηθούν μεγέθη, που δηλώθηκαν στο κύριο πρόγραμμα. Το όνομα συνάρτησης κανονικά μπορεί να βρίσκεται μόνο στα αριστερά του “:=” σε μια εντολή καταχώρησης. Εξαίρεση έχουμε κατά την αναδρομή (recursion), όπου μια συνάρτηση καλεί τον εαυτό της.
Κανόνες Συναρτήσεων Μία συνάρτηση καλείται με το όνομά της, ακολουθούμενο από μια λίστα με τις επίκαιρες ή πραγματικές (actual) παραμέτρους: όνομα_συνάρτησης(επίκαιρη_παράμετρο ς1,επίκαιρη_παράμετρος2,…,επίκαιρη_πα ράμετροςΝ)
Κανόνες Συναρτήσεων Οι επίκαιρες παράμετροι κατά την κλήση, αντιστοιχούν στις τυπικές παραμέτρους, που υπάρχουν στη δήλωση της συνάρτησης. Εκτός των άλλων πρέπει και να συμφωνούν και οι τύποι των παραμέτρων. Μία συνάρτηση, που δεν έχει παραμέτρους, καλείται μόνο με το όνομά της. Η κλήση μιας συνάρτησης έχει σαν αποτέλεσμα μία τιμή της συνάρτησης να υπολογιστεί. Η τιμή αυτή έχει τον τύπο, που ορίστηκε στην επικεφαλίδα συνάρτησης.
Συναρτήσεις - Παράδειγμα Παράδειγμα : Υπολογισμός αθροίσματος 1+2+3+…+Ν. Program sumnum; Uses crt; Var n : Integer; Sum : Longint; Function nsum(n : Integer) : Longint; Var i : Integer; Total : Longint; Begin Total := 0; For i := 1 To n Do total := total + i; Nsum := total; End; Begin Clrscr; Write(‘Δώσε ένα αριθμό: ‘); Readln(n); Sum := nsum(n); Writeln(‘Τα άθροισμα των πρώτων ‘,n,’ αριθμών είναι: ‘,sum); Readln; End.
ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ (local) Παρατηρήστε στο παράδειγμα της προηγούμενης διαφάνειας ότι τόσο το πρόγραμμα όσο και η συνάρτηση κάνουν χρήση μιας μεταβλητής n. Πρόκειται για διαφορετικές μεταβλητές. Η παράμετρος της συνάρτησης είναι η τιμή και όχι η ίδια η μεταβλητή n (αυτό θα συνέβαινε αν η παράμετρος ήταν Var n). Έτσι η μεταβλητή n στο εσωτερικό της συνάρτησης είναι τοπική μεταβλητή. Μία τοπική μεταβλητή μπορεί να έχει ίδιο όνομα με μια μεταβλητή του προγράμματος χωρίς να έχει καμία επίδραση στην τιμή της.
ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ (local) Αν στο εσωτερικό ενός υποπρογράμματος ορίσουμε μια τοπική μεταβλητή με το όνομα μιας τυπικής παραμέτρου, το αποτέλεσμα θα είναι το μήνυμα “Duplicate identifier” (διπλό όνομα), που αποδεικνύει ότι υπάρχει ήδη τοπική μεταβλητή με αυτό το όνομα.
ΚΑΘΟΛΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ (global) Είναι οι μεταβλητές του κύριου προγράμματος στις οποίες μπορεί να επιδρούν εκτός από το κύριο πρόγραμμα και στα υποπρογράμματα.
Δήλωση Διαδικασιών Μία δήλωση διαδικασίας διαφέρει από μία δήλωση συνάρτησης τόσο στην επικεφαλίδα, όσο και στο ό,τι το όνομα διαδικασίας δε παίρνει κάποια τιμή. Procedure όνομα_διαδικασίας(τυπικοί_παράμετροι); {Εδώ γράφονται οι τοπικές δηλώσεις της διαδικασίας, αν υπάρχουν} Begin {Εδώ γράφονται οι εντολές που εκτελούνται, όταν η διαδικασία καλείται} End;
Δήλωση Διαδικασιών Μία διαδικασία καλείται σαν μια εντολή, που αποτελείται μόνο από το όνομα_διαδικασίας και τις επίκαιρες παραμέτρους (πραγματικές). Μία διαδικασία χωρίς παραμέτρους καλείται μόνο με το όνομά της. όνομα_διαδικασίας(επίκαιρη_παράμετρος1,επίκαιρη_παράμετρος2,…,επίκαιρη_παράμετροςΝ);
Παράδειγμα Διαδικασίας Παράδειγμα : Υπολογισμός αθροίσματος 1+2+3+…+Ν. Program sumnum; Uses crt; Var n : Integer; Sum : Longint; Procedure nsum(n : Integer;Var total:Longint); Var i : Integer; Begin Total := 0; For i := 1 To n Do total := total + i; End; Begin Clrscr; Write(‘Δώσε ένα αριθμό: ‘); Readln(n); Nsum(n,sum); Writeln(‘Τα άθροισμα των πρώτων ‘,n,’ αριθμών είναι: ‘,sum); Readln; End.
Παράμετροι Διαδικασιών Οι τυπικές παράμετροι μιας διαδικασίας χωρίζονται σε δύο κατηγορίες: Παράμετροι τιμών Var παράμετροι Στην επικεφαλίδα του υποπρογράμματος ορίζει κανείς μέσα σε παρένθεση τα ονόματα των τυπικών παραμέτρων, την κατηγορία και τον τύπο τους. π.χ. Procedure sum(a : integer; b : integer; c : integer; Var d : longint);
Παράμετροι Διαδικασιών Αν πολλές παράμετροι στη σειρά είναι ίδιας κατηγορίας και του ίδιου τύπου η επικεφαλίδα μπορεί να γραφτεί πιο απλά. π.χ. Procedure sum(a, b, c : integer; Var d : longint); Οι μεταβλητές a, b, c είναι παράμετροι τιμών και η d Var παράμετρος. Πρέπει να σημειώσουμε ότι ο τύπος μιας τυπικής παραμέτρου δίνεται πάντοτε με ένα όνομα standard τύπου ή τύπου που προηγούμενα δηλώθηκε. Η ακόλουθη επικεφαλίδα είναι λανθασμένη: Procedure sum(a , b :integer; Var c : array[1..5] of integer);
Παράμετροι Τιμών Μία παράμετρος, που η αποστολή της είναι να εφοδιάσει το υποπρόγραμμα με μία τιμή, δηλώνεται σαν παράμετρος τιμής. Κατά την κλήση η τυπική αυτή παράμετρος πρώτα παίρνει τιμή από την αντίστοιχη επίκαιρη παράμετρο. Κατόπιν χρησιμοποιείται σαν τοπική μεταβλητή μέσα στο υποπρόγραμμα. Μία επίκαιρη παράμετρος, που αντιστοιχεί σε μία τυπική παράμετρο τιμής, θα είναι μια μεταβλητή, σταθερά, συνάρτηση ή μια παράσταση του ιδίου τύπου.
Παράμετροι Τιμών Οι τιμές των επίκαιρων (πραγματικών) παραμέτρων υπολογίζονται μία μόνο φορά, όταν γίνεται η κλήση. Αν στο υποπρόγραμμα καταχωρήσει κανείς μία τιμή σε μια τυπική παράμετρο τιμής, η καταχώρηση αυτή δεν επηρεάζει την αντίστοιχη επίκαιρη παράμετρο.
Παράμετροι Τιμών Οι τυπικές και επίκαιρες (πραγματικές) παράμετροι πρέπει να συμφωνούν στο πλήθος και στον τύπο. Είναι επιτρεπτό η επίκαιρη παράμετρος να είναι τύπου integer και η αντίστοιχη τυπική παράμετρος να είναι τύπου real. Η ακέραια τιμή μετατρέπεται αυτόματα σε πραγματική.
Var Παράμετροι Μία παράμετρος, που έχει σαν αποστολή να μεταφέρει μια τιμή «έξω» από το υποπρόγραμμα, προς το πρόγραμμα που καλεί, πρέπει να δηλωθεί σαν Var παράμετρος. Αυτό ισχύει και για τις παραμέτρους που έχουν διπλή αποστολή, δηλ. και να εφοδιάσουν το υποπρόγραμμα με μία τιμή και να μεταφέρουν μία τιμή από το υποπρόγραμμα προς το πρόγραμμα που καλεί. Η τυπική παράμετρος του υποπρογράμματος αναφέρεται στο χώρο μνήμης, που καταλαμβάνει η αντίστοιχη επίκαιρη παράμετρος.
Var Παράμετροι Μια επίκαιρη παράμετρος, που αντιστοιχεί σε μία τυπική var παράμετρο, θα είναι μια μεταβλητή του ίδιου τύπου. Όταν έχουμε παραμέτρους τιμών, δημιουργούνται κατά την κλήση τοπικές μεταβλητές, που παίρνουν τις τιμές τους από τις αντίστοιχες επίκαιρες παραμέτρους. Στη συνέχεια το υποπρόγραμμα δουλεύει με αυτές τις τοπικές μεταβλητές.
Var Παράμετροι Όταν έχουμε Var παραμέτρους, το υποπρόγραμμα αναφέρεται απευθείας στις επίκαιρες παραμέτρους και μπορεί να επηρεάσει την τιμή τους. Όταν μία παράμετρος είναι μία μεταβλητή, που καταλαμβάνει μεγάλο χώρο μνήμης, συνηθίζει κανείς να τη δηλώνει σαν var παράμετρο. Έτσι εξοικονομείται ο χώρος μνήμης, που θα καταλάμβανε η τοπική μεταβλητή, εάν ήταν παράμετρος τιμής.
Αναδρομή (Recursion) Το πεδίο ορισμού ενός υποπρογράμματος αρχίζει με την επικεφαλίδα και τελειώνει με τη λέξη end του τμήματος το οποίο το ορίζει. Έτσι, ένα υποπρόγραμμα μπορεί μέσα από το πεδίο ορισμού του να καλεί ένα άλλο υποπρόγραμμα ή ακόμη και τον ίδιο τον εαυτό του. Μια διαδικασία ή συνάρτηση η οποία μεταξύ των διαφόρων εντολών περιέχει και μία τουλάχιστον κλήση στον εαυτό της, ονομάζεται διαδικασία ή συνάρτηση με αναδρομή.
Αναδρομή (Recursion) Πολλοί ορισμοί, υπολογισμοί και αλγόριθμοι περιγράφονται ευκολότερα και με πιο συνοπτικό τρόπο με τη χρήση αναδρομής. Αυτό φανερώνει ότι η αναδρομή είναι αλγοριθμική δομή πληρέστερη από την επανάληψη. Όλοι οι ορισμοί με αναδρομή έχουν δύο κοινά χαρακτηριστικά: ένα στοιχείο που ελέγχει την αναδρομή, ένα μηχανισμό που επιτρέπει την έξοδο από τη διαδικασία.
Παράδειγμα Αναδρομής Υπολογισμός του Ν παραγοντικό με αναδρομή. Function Factorial(n : Integer) : Integer; Begin If n = 0 then Factorial := 1 Else Factorial := n*Factorial(n-1); End;
Παράδειγμα Αναδρομής
Βιβλιογραφία Σχολικό Βιβλίο: Προγραμματισμός Υπολογιστών Σημειώσεις Πετρίδη Συμεών – Καθηγητής Πληροφορικής ΠΕ20 – ΕΠΑΛ Νάουσας