ΣΥΝΑΡΤΗΣΕΙΣ ( FUNCTION ) Είναι άλλο είδος υποπρογραµµάτων Είναι παρόµοιες µε τις διαδικασίες αλλά επιστρέφουν στο πρόγραµµα που τις κάλεσε ΜΙΑ µόνο τιµή (µέσω του ονόµατός τους ) Αποτελείται από την επικεφαλίδα της µε τη δεσµευµένη λέξη FUNCTION και το όνοµα της ίπλα µέσα σε παρένθεση ακολουθούν οι παράµετροι ορισµού ( είναι παράµετροι τιµής µόνο) και µετά δηλώνεται τι τύπος θα είναι η τιµή που θα επιστρέψει η συνάρτηση Πχ FUNCTION MaxAkeraio (a, b : integer ) : integer ; if a > b then MaxAkeraio := a else MaxAkeraio := b; end; Ανάµεσα στους χειρισµούς µιας διαδικασίας και µιας συνάρτησης υπάρχουν διαφορές Πχ Εύρεση µεγαλυτέρου δύο αριθµών Program ProcedureKaiFunction; var z, x, PMax, FMax : integer ; Procedure Megisto ( k, v : integer ; var m : integer ); if k > v then m := k else m := v; end ; { procedure } Function MaxAkeraio (a, b : integer ) : integer; if a > b then MaxAkeraio := a else MaxAkeraio := b ; end; { function } z := 4 ; x := 9 ; Megisto ( z, x, PMax ) ; writeln ( Ο µέγιστος στη Procedure βρέθηκε, PMax ) ; FMax := MaxAkeraio (z, x ) ; writeln ( Ο µέγιστος στη Function βρέθηκε, FMax ) ; end ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 1 Γλώσσα ΠρογραµPASCAL
Στατικές οµές εδοµένων ΤΥΠΟΙ που ορίζονται από τον χρήστη 1) Οι επτά ηµέρες της εβδοµάδος έχουν ένα όνοµα η κάθε µία Μπορούµε να συµφωνήσουµε να λέµε ένα και να εννοούµε ευτέρα κλπ Όµως αυτό κάνει το πρόγραµµα δυσνόητο για κάποιον που δεν ξέρει την αντιστοιχία ή την ξεχάσει αργότερα Η Pascal µας επιτρέπει να ορίσουµε δικούς µας τύπους και να κάνουµε τα προγράµµατα πιο ευανάγνωστα 2) Πχ type DAY = (kyriakn, deutera, Tritn, Tetartn, Pemptn, Paraskeun, Sabato ); Οι τιµές που µπορεί να πάρει ο τύπος DAY έχουν µια σειρά που αρχίζει πάντα από το µηδέν για την πρώτη τιµή 3) Ετσι η Tritn είναι µικρότερη της Tetartn και µεγαλύτερη τηςdeutera Sabato Paraskeun 6 Pemptn 5 Tetartn 4 Tritn 3 Deutera 2 Kyriakn 1 0 4) Var nmera, ergasimn, nmiargia, weekend : DAY; b, a, seira : integer; epidoma argias : real; 5) Μέσα από το πρόγραµµα µπορώ να κάνω Α) εκχωρήσεις nmera := Pemptn; (όπως a := 154 ;) Pemptn nmera Ergasimn := nmera; (όπως b := a; ) Pemptn ergasimn ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 2 Γλώσσα ΠρογραµPASCAL
Β) συγκρίσεις IF nmera >= Sabato THEN writeln ( Σήµερα είναι Κυριακή ) ; Γ) εύρεση σειράς που έχει ( εξ ορισµού ) 0 seira Seira := ORD ( Kyriakn ); (όπως a := ord ( A ) ; ) )Ergasimn := succ ( Tritn ); Ergasimn := succ ( nmera ); Weekend := pred (Deutera ); Tetartn Paraskeun Kyriakn ergasimn ergasimn weekend Ergasimn := succ (Sabato ) ; ΕΝ ΟΡΙΖΕΤΑΙ ΑΡΑ ΙΝΕΙ ΛΑΘΟΣ Ο COMPILER Ε) σαν απαριθµητοί τύποι µπορούν να χρησιµοποιηθούν ως τιµές και στο καταµετρητή µιας εντολής FOR FOR nmera := Kyriakn TO Sabato do If ( nmera >= Deutera ) AND ( nmera <= Paraskeun ) Then write ( ord (nmera), Η ηµέρα είναι εργάσιµη ) Else write ( ord ( nmera ), Η ηµέρα είναι αργία ) ; ΣΤ) χρησιµοποιούνται ως µεταβλητές επιλογής σε CASE : Case nmera Of Kyriakn : epidomaargias := 200 ; Sabato : epidoma argias := 150 ; Deutera, Tetartn, Paraskeun : epidoma argias := 125 ; Tritn, Pemptn : epidoma argias := 100; End ; { case } 6) τι ΕΝ επιτρέπεται να κάνω µέσα σ ένα πρόγραµµα Τους Τύπους που εισάγονται από τον χρήστη δεν µπορώ ούτε να τους τυπώσω ούτε να τους εισάγω από το πληκτρολόγιο Readln ( nmera ) Writeln ( nmera ) Writeln ( ord ( nmera ) ) ΣΩΣΤΟ ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 3 Γλώσσα ΠρογραµPASCAL
Για να πετύχω να τυπώσω type DAY = (kyriakn, deutera, Tritn, Tetartn, Pemptn, Paraskeun, Sabato ); procedure TypwmaHmeras (mera : day ); case mera of Kyriakn : writeln ( Κυριακή ) Deutera : writeln ( ευτέρα ) Sabato : writeln ( Σάββατο ) Else : writeln ( απροσδιόριστη τιµή ) end ; { case } Για να πετύχω να διαβάσω : type DAY = (kyriakn, deutera, Tritn, Tetartn, Pemptn, Paraskeun, Sabato ); procedure eisagogihmeras ( var mera : day ); var number : ineger; repeat writeln( 1 Κυ, 2 ε, 3 Τρ, 4 Τε, 5 Πε, 6 Πα, 7 Σα ); readln (number ) ; until ( ( number >= 1 ) and ( number <= 7 ) ) ; case number of 1 : mera := Kyriaki; 2 : mera := Deutera 7 : mera := Sabato; end ; { case } ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 4 Γλώσσα ΠρογραµPASCAL
7) Επειδή µετά το Sabato έρχεται Kyriakn για να µην έχω λάθος στον Compiler όταν δίνω nmera := scc ( Sabato ) έχουµε Const prwtnmera = Kyriakn; TeleutaiaMera = Sabato; Function EpomevnMera (snmera : day ) : day; Begin If ( snmera = TeleutaiaMera ) Then EpomevnMera := PrwtnMera Else EpomevnMera := succ (EpomevnMera ) ; End ; {function } 8) Τύποι που ορίζονται από τον χρήστη στο κυρίως πρόγραµµα αναγνωρίζονται από τις διαδικασίες ή τις συναρτήσεις Τύποι ΥΠΟΠΕΡΙΟΧΗΣ οριζόµενοι από τον χρήστη 1) Type xronologia : 1955 1988; Var EtosGennesis : xronologia ; 2) ΠΑΡΑΤΗΡΗΣΗ Μπορεί η δήλωση Var EtosGennesis ; 19955 1988; να είναι σωστό και φαίνεται καλύτερη αλλά θα δηµιουργήσει προβλήµατα αν χρειαστεί να υπάρξει τύπος σε διαδικασία ή συνάρτηση 3) type Day = ( Kyriakn,, Sabato ) ; Douleia = Deutera Paraskeyn ; ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 5 Γλώσσα ΠρογραµPASCAL
ΕΓΓΡΑΦΕΣ ( RECORDS ) Ανήκει στις στατικές δοµές δεδοµένων Χρησιµοποιούνται για να κατακρατούν διαφορετικά είδη δεδοµένων ( διαφορετικά κοµµάτια πληροφορίας τα οποία µπορεί να είναι διαφορετικών τύπων Όπως είναι οι εγγραφές σ ένα αρχείο 1) Πως δηλώνουµε µια εγγραφή Type Student = Record Name : string [20 ]; Address : string [ 30 ]; City : string [10 ]; End ; 2) Πως δηµιουργούµε µεταβλητές Var Pupil Pupil : student; StudentList : Array [ 1 100 ] of student ; { δηλώνουµε πίνακα } Name Address City PupilName StudentList Name Addr ess PupilAddress PupilCity City Name Addr ess City Name Addr ess City StudentList [ 1 ] StudentList[ 2 ] StudentList [ 100 ] StudentList[1]Name StudentList[1]Address StudentList[1]City 3) Πως εκχωρούµε τιµές στις µεταβλητές τύπου Record Pupil Name := ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ ; StudentList [ 1 ] Name := ΤΑ Ε ΤΑ ΟΠΟΥΛΟΣ ; StudentList [ 2 ] Name := ΕΙΝΑ ΕΙΝΟΠΟΥΛΟΣ ; ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 6 Γλώσσα ΠρογραµPASCAL
4) Εστω κάποιος µε 4 τηλέφωνα Address = Record Odos : string [ 15 ]; Arithmos : integer ; Poli : string [ 15 ] ; Tel : array [ 1 4 ] of string [ 15 ]; End ; Εντολή WITH Αντί να γράφουµε Var Addr : address; Begin End Readln (addr odos ); Readln (addr arithmos); Readln (addr poli ) ; Readln ( addr tel [ 1 ] ) ; Γράφουµε Var Addr : address; Begin With addr do Readln ( odos ); Readln ( arithmos ) ; Readln ( poli ) ; Readln ( tel [ 1 ] ) ; End ; { with } End 5) Για να διαβάζουµε όλα τα τηλέφωνα Var Addr : address; Begin With addr do Readln ( odos ); Readln ( arithmos ) ; Readln ( poli ) ; For I := 1 to 4 do Begin Write ( ώστε, I, ο τηλέφωνο ) Readln ( tel [ I ] ) ; End ; {for } End ; { with } End ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 7 Γλώσσα ΠρογραµPASCAL
6) Ιεραρχικές εγγραφές λέγονται αυτές που µπορεί να έχει ως πεδίο και άλλες εγγραφές Τα απαραίτητα στοιχεία αστυνοµικής ταυτότητας είναι TAYTOTHTA = Record Arithmos : string [ 7 ]; Ekd_arxn : string [ 20 ]; Hmer_Ekdosis : Record Mera : 1 31 ; Mnvas : 1 12 ; Etos : 1900 2100 ; End ; { TAYTOTHTA } Η µπορούµε ισοδύναµα να δηλώσουµε Hmeromnvia = Record Mera : 1 31 ; Mnvas : 1 12 ; Etos : 1900 2100 ; End ; {Hmeromnvia } TAYTOTHΤΑ = Record Arithmos : string [ 7 ]; Ekd_arxn : string [ 20 ]; Hmer_Ekdosis : Hmeromnvia ; End ; { TAYTOTHTA } Ο δεύτερος τρόπος υπερέχει του πρώτου Για να κρατήσουµε στοιχεία κάποιου ανθρώπου χρειαζόµαστε µια εγγραφή σαν την παρακάτω Type Anthrwpos = Record Gevika : Genika_stoixeia; Topos_Gevvnsns : string [ 15 ] ; Xrovos_Gevvnsns : Hmeromnvia ; Tautotnta : Taytotn ; Dieuthnvsn : Address ; Var Ypallnlos : anthrwpos ; Begin Readln ( ypallnlosgevikaonoma Readln ( ypallnlosxrovos_gevvnsnsmnvas ) ; Readln (ypallnlostaytotntanmer_ekdosismnvas ) ; End ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 8 Γλώσσα ΠρογραµPASCAL
7) Ας δούµε ένα παράδειγµα µιας εγγραφής για την περιγραφή της σκακιέρας Type Eidos_Kommatiou = ( empty, pioneer, horese, bishop, tower, Xrwmma_Paiktn = ( Kavena, maura, aspra ); Tetragwvo = Record Katnlnmevo : boolean ; Kommati : Eidos_Kommatiou ; Paiktns : Xrwma_Paiktn ; End ; { record tetragwvo } queen, king); Skaki = Array [ A H, 1 8 ] of Tetragwvo ; Ας δηλώσουµε τώρα µια µεταβλητή Skakiera και ένα τετράγωνο το οποίο χρησιµοποιούµε για να περιγράψουµε µια TrexousaKivnsn Var Skakiera : skaki; TrexousaKivnsn : Tetragwvo ; Begin TrexousaKivnsn Katnlnmevo := true; TrexousaKivnsn Kommati := bishop ; TrexousaKivnsn Paiktns := aspra ; Skakiera [ c, 7] := TrexousaKivnsn ; {αντιγράφουµε το περιεχόµενο ολόκληρης της εγγραφής δηλ στο τετράγωνο(c,7 ) } skakiera [ g, 3 ] := Skakiera[ c,7];{ αντιγράφουµε το περιεχόµενο του τετραγώνου c, 7 ) στο τετράγωνο ( g,3 ) } skakiera [ H, 4 ] Katnlnmevo := true; skakiera [ H, 4 ] Kommati := tower ; skakiera [ H, 4 ] paiktns := maura ; End; ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 9 Γλώσσα ΠρογραµPASCAL
ΕΓΓΡΑΦΕΣ ΜΕΤΑΒΛΗΤΟΥ ΜΗΚΟΥΣ Όπως περιγράψαµε την εγγραφή tetragwvo Σκακιού έχει ένα µειονέκτηµα ότι χρειάζεται να δίνουµε τιµές σ ένα άδειο τετράγωνο ιαφαίνεται λοιπόν η ανάγκη να υπάρξει ένας µηχανισµός που ανάλογα µε την τιµή που παίρνει το πεδίο Katnlnmevo να έχει νόηµα ή όχι η διερεύνηση των πεδίων Kommati και Paiktns Ο µηχανισµός υλοποιείται µε µια case Type Grammn : A, H ; Stnln : 1 8 ; Eidos_Kommatiou=(pioneer,horse,bishop,tower,queen,king) Xrwmma_Paiktn = ( maura, aspra ); Tetragwvo = Record Case Katnlnmevo : boolean of True : ( Kommati : Eidos_Kommatiou ; Paiktns : Xrwma_Paiktn ;) ; False : ( ) ; End ; { record tetragwvo } Skaki = Array [ Grammn, Stnln ] of Tetragwvo ; Παρατηρήσεις : α) Το case εδώ χρησιµοποιείται στον ορισµό του τύπου της (περιοχή type ) και όχι στην περιοχή που γράφεται ο κώδικας του προγράµµατος µε τις εντολές β) Μόνο στην περίπτωση που πεδίο Katnlnmevo έχει την τιµή True έχουν έννοια οι τιµές των πεδίων Kommati και Paiktns γ) Στο case στην περίπτωση των εγγραφών µεταβλητού µήκους πρέπει να δηλώνεται και ο τύπος της µεταβλητής η οποία καθορίζει τις επιλογές (το πεδίο Katnlnmevo ) δ) Τα πεδία που ορίζονται µέσα στο case παρατίθενται µέσα σε Παρενθέσεις και δεν υπάρχει end στο τέλος της case Aνάλογα µε την τιµή που παίρνει η µεταβλητή Katnlnmevo τα υπόλοιπα πεδία υπάρχουν ή όχι Αν µια µεταβλητή έχει στο πεδίο Katnlnmevo τιµή true τότε οι πληροφορίες που υπάρχουν στα επόµενα πεδία ερµηνεύονται ως πεδία Kommati και Paiktns πχ Katnlnmevo Kommati Paiktns Αν µια µεταβλητή έχει στο πεδίο Katnlnmevo τιµή false τότε οι πληροφορίες που υπάρχουν στα επόµενα πεδία αγνοούνται Katnlnmevo ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 10 Γλώσσα ΠρογραµPASCAL
ΥΝΑΜΙΚΕΣ ΟΜΕΣ Ε ΟΜΕΝΩΝ ΕΙΚΤΕΣ Οί πίνακες δεν είναι ευέλικτοι και µερικές φορές τείνουν να ξοδέψουν το χώρο µνήµης του υπολογιστή σας Για να είστε σίγουροι ότι έχετε αρκετό χώρο για όλα τα δεδοµένα σας πρέπει να έχετε αρκετά µεγάλους πίνακες Μπορεί όµως να τελειώσει η µνήµη σας Αν προσπαθήσετε να κόψετε το µέγεθος του πίνακα για να εξοικονοµήσετε χώρο τότε µπορεί να έχετε πρόβληµα υπερχείλησης δηλ να έχετε περισσότερα δεδοµένα από όσα χωρούν στο πίνακα Επίσης εισαγωγή, διαγραφή στοιχείων στη µέση ενός ταξινοµηµένου πίνακα είναι αρκετά επίπονη εργασία Η λύση είναι η δυναµική κατανοµή της µνήµης Παρά το περίπλοκο πρόβληµα η ιδέα της κατανοµής είναι απλή Οταν µεταγλωτίζεται ένα πρόγραµµα η PASCAL δεσµεύει ένα συγκεκριµένο ποσό µνήµης για όλες τις µεταβλητές που δηλώνονται στο πρόγραµµα (var) Αργότερα όταν το πρόγραµµα εκτελείται από τον χρήστη οι αποφάσεις για την κατανοµή της µνήµης έχουν ήδη γίνει και δεν µπορούν να αλλάξουν Γι αυτό το λόγο λέγεται στατική κατανοµή της µνήµης Η δυναµική κατανοµή της µνήµης γίνεται κατά την εκτέλεση του προγράµµατος Οι αποφάσεις για την κατανοµή της µνήµης παίρνονται και οι µεταβλητές δηµιουργούνται κατά την εκτέλεση ενός προγράµµατος Τα χαρακτηριστικά σ αυτή τη κατανοµή είναι ο δείκτης Τα προβλήµατα που δηµιουργούνται είναι : 1) να ξέρουµε ποιές µεταβλητές χρησιµοποιούνται και 2) να εντοπίζουµε σε ποιό σηµείο της µνήµης βρίσκονται αποθηκευµένες είκτης είναι ένα ειδικό είδος µεταβλητής που λύνει αυτά τα προβλήµατα Αντί να περιέχει ένα ακέραιο, µια συµβολοσειρά κλπ ο δείκτης κρατά τη διεύθυνση µνήµης µιας άλλης µεταβλητής που µπορεί να µην υπάρχει κατά την µεταγλώττιση του προγράµµατος Σαν κάθε µεταβλητή ορίζεται έτσι ώστε να εργάζεται µε στοιχεία ενός συγκεκριµένου τύπου Οι δυναµικές µεταβλητές δεν περιέχουν τις ίδιες τις τιµές, αλλά µόνο τη διεύθυνση της τιµής είχνουν σε µια περιοχή της µνήµης Γι αυτό και οι µεταβλητές αυτές ονοµάζονται δείκτες υναµικές µεταβλητές σηµαίνει ότι σ αυτές διατίθεται µνήµη µόνο κατά τη διάρκεια της εκτέλεσης του προγράµµατος Στις δυναµικές µεταβλητές διατίθεται η συνολική µνήµη σωρού ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 11 Γλώσσα ΠρογραµPASCAL
Πως δηλώνουµε ένα τύπο δείκτη Var a, b, c : ^integer ; Ή καλύτερα δηλωµένα Type NumInt = ^ Integer; Begin Var a, b, c : NumInt ; new ( a ); new ( b ) ; new ( c ) ; a^ := 1 ; b^ := 2 ; c^ := 3 ; Writeln ( a^ : 4, b^ :4, c^ : 4 ) ; Άλλο παράδειγµα TYPE MyFirstPointer = ^ Integer; MySecondPointer=^MyPointerDataItem; MyPointerDataItem=record name : string[10]; age : ineger; paid : boolean; end; ή απλούστερα TYPE deiktis = ^ a; a = record name : string[10]; age : ineger; paid : boolean; end; Ο πρώτος δείκτης που δηλώνουµε θα δείχνει σε δυναµικές µεταβλητές τύπου integer Ο δεύτερος τύπος δείκτη MySecondPointer θα δείχνει µόνο σε στοιχεία τύπου MyPointerDataItem Εδώ βλέπουµε µια εξαίρεση στον κανόνα δήλωση πριν τη χρήση Οταν δηλώνουµε ένα τύπο δείκτη που δείχνει σε ένα τύπο δεδοµένων που ορίζεται από το χρήστη η Pascal υποθέτει ότι πρόκειται να δηλώσετε ένα δεύτερο τύπο πριν το τέλος του τοµέα type Αφού δηλώσουµε τύπους δείκτη στον τοµέα type µπορούµε να δηµιουργήσουµε µεταβλητές αυτού του τύπου στον τοµέα var VAR NumPtr : MyFirstPointer; Recptr : a; Σηµείωση : Οι δείκτες είναι στατικές µεταβλητές ώστε να υπάρχει κάποιο σταθερό σηµείο µε το οποίο να συνδέονται οι δυναµικές Ετσι η NumPtr είναι µεταβλητή αλλά όχι ακέραια Είναι µεταβλητή δείκτης που δείχνει σε δυναµική µεταβλητή ακέραια Είναι δε στατική µεταβλητή Η NumPtr^ είναι η δυναµική ακέραια µεταβλητή ΠΡΟΣΟΧΗ το ^ προηγείται κατά τον ορισµό του τύπου (στο type) και ακολουθεί στο όνοµα της µεταβλητής στο οποίο αναφέρεται ο δείκτης ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 12 Γλώσσα ΠρογραµPASCAL
Χειρισµός Type deiktis = ^char; index = ^ integer; Var a,b,e,f : deiktis; c,d : index; Begin new(a); new(b); writeln( a^=,a^); a^ := k ; b^ := L ; writeln( a^=,a^); writeln( b^=,b^); b^ := a^; b^ := @ ; b^ := a^; a^ := g ; b^ := a^; ch := a^; b := a; a^ := I ; writeln( a^=,a^); writeln( b^ =,b^); b^ := * ; writeln( a^ =, a^); writeln( b^ =,b^); δεικτών ορισµός δεικτών ορισµός µεταβλητών τύπου δείκτη υναµική παραχώρηση µνήµης a b εµφανίζει τα της θέσης µνήµης e µεταφρασµένα στον f τύπο της a πχ a: boolean false H TPW δίνει αρχικές a τιµές b Εκχώρηση τιµών εκεί που δείχνει ο δείκτης Εµφανίζει τις τιµές e που έχω δώσει ( α^ f k, b^ L ) Εκχωρεί τις τιµές ενός δείκτη σε άλλο είχνεται η διαφορά εκχώρησης τιµών ch Εκχώρηση σε στατική µεταβλητή από δυναµική Εκχωρούµε τη δ/νση ενός δείκτη σε ένα άλλο Οι δύο δείκτες δείχνουν την ίδια µεταβλητή a b e f a b a b Στατικές µεταβλ 687544 687544 k ' υναµικές µεταβλητές περιεχόµ ε περιεχόµ ε L' ' k' ' I ' 'k' ' I ' ' * ' 687542 687543 687544 687545 687546 687542 687543 687544 687545 687546 687542 687543 687544 687545 687542 687543 687544 687545 687542 ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 13 Γλώσσα ΠρογραµPASCAL
ΠΡΟΣΟΧΗ Αν και ο δείκτης b θα δείχνει στη διευθυνση του α η προηγούµενη διεύθυνση 687544 δεν ελευθερώνεται για να δοθεί σε προσεχές New Ετσι η διεύθυνση 687544 παραµένει οριστικά χαµένη New(b); Παραχωρείται νέα θέση µνήµης για τη µεταβλητή b^ Η 687544 ΕΝ µπορεί να παραχωρηθεί ξανά ΠΧ παραχωρείται η 687543 New(b); Παραχωρείται νέα θέση µνήµης για τη µεταβλητή b^ Η 687544 όπως και η 687543 ΕΝ µπορεί να 68754 παραχωρηθεί ξανά a Αρα έχουµε δύο τρόπους να σπαταλούµε µνήµη b 68753 b:=a; new(b); 687542 687543 6875444 Αν δεν χρειαζόµαστε κάποιο δείκτη και προκειµένου να ελευθερωθεί η µνήµη για µελλοντική χρήση µε New τότε δίνουµε την εντολή Dispose (b); Αποδεσµεύει τη θέση µνήµης που είχε δεσµευθεί για τη µεταβλητή b^ επιτρέποντας στον Η/Υ να την χρησιµοποιήσει σε µελλοντικό New Η µεταβλητή b^ αν και θεωρείται σαν να µην υπάρχει επειδή ο δείκτης b συνεχίζει να έχει τη διεύθυνση της µπορεί να τυπωθεί το περιεχόµενο της Τέτοια πράγµατα δεν συνιστώνται για την οµαλή λειτουργία ενός προγράµµατος New(e); New(f); e := b; Οι δείκτες δείχνουν στην ίδια διεύθυνση f :=e ; writeln (b^, e^, f^ ); dispose(b); dispose(f); ΠΡΟΣΟΧΗ Στην TPW έχει σαν αποτέλεσµα να µην έχει περιεχόµενο ούτε η b^, ούτε η e^, ούτε η f^ Στην Standard Pascal θα αποδεσµευθεί η µνήµη που είχε κρατηθεί για τη b Αλλά η ίδια θέση θα παραµένει δεσµευµένη από τα e, f Η δ/νση θα µπορούσε να παραχωρηθεί µε νέο New µετά την εκτέλεση των εντολών dispose(e); dispose(f); Κατά κανόνα το περιεχόµενο ενός δείκτη (η δ/νση) ούτε µπορεί να ορισθεί ούτε µπορεί να εµφανίζεται στην οθόνη (Στη SVS Pascal τυπώνεται) Το µόνο που µπορεί να γίνει είναι η σύγκριση µε τιµή άλλου δείκτη ή nil If (a=b) then writeln ( είχνουν την ίδια διεύθυνση ) else writeln ( ΕΝ είχνουν την ίδια διεύθυνση ) ; 687545 ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 14 σηµειώσειςpascal
Πριν προχωρήσουµε στην υλοποίηση σωρού και ουράς µε τη βοήθεια δεικτών ας δούµε µερικά χρήσιµα και κατατοπιστικά παραδείγµατα Type a = ^stoixeio; stoixeio=record data:integer; xt : a; end; var arxn,telos, trexwv,t1,t2: a; Begin new(arxi); new(telos); new(trexwn); trexwn := arxi; telos := arxi; new( t1 ) ; t1 := arxi; t1 := t1^next; ορισµός τύπου α δείκτη που δείχνει σε µια µεταβλητή τύπου record µε δύο θέσεις Μια για ακεραίο και µια για δείκτη τύπου α ορισµός µεταβλητών τύπου δείκτη α υναµική παραχώρηση µνήµης ηλ η στατική τεταβλητή arxi δείχνει σε µια (!) θέση µνήµης δυναµική τύπου stoixeio που είναι ένα record µε µια θέση για καταχώρη-ση δεδοµένου και µια θέση για δείκτη Στις θέσεις αυτές αναφέροµαι µε τα ονόµατα όπως φαίνεται δεξιά της στήλης δυναµικής µνήµης Εκχωρεί τις τιµές ενός δείκτη σε άλλο ηλ πλέον η θέση µνήµης µε περιεχό-µενο 777 µπορεί να προσπελασθεί µε τρία ονόµατα arxi^data trexwn^data telos^data Εκχωρούµε τη δ/νση ενός δείκτη σε ένα άλλο ηλ ο t1 δείχνει πλέον σε νέα δ/νση αυτή που δείχνει ο t1^next arxi trexw telos t1 arxi trexw telos t1 arxi t1 arxi t1 Στατικές Μεταβλητ 687546 687548 υναµικές δεδοµ ένο 777 δ είκτης --> δ εδ ο µ ένο δ είκτης --> δ εδ ο µ ένο δ είκτης --> δεδοµ ένο 777 δείκτης --> δεδοµ ένο 777 δ /νση 687548 δεδοµ ένο 32 δ /νση 68755 δεδοµ ένο 777 δ /νση 687548 δεδοµ ένο 32 δ /νση 68755 arxi^data δ/νση arxi^next trexwn^data trexwn^next telos^data telos^next arxi^data telos^data trexwn^data arxi^next telos^next trexwn^next arxi^data t1^data arxi^next t1^next δ/νση 68758 arxi^data arxi^next δ/νση 68758 t1^data t1^next ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 15 σηµειώσειςpascal
ΛΙΣΤΕΣ ΗΜΙΟΥΡΓΙΑ ΑΤΑΞΙΝΟΜΗΤΗΣ ΛΙΣΤΑΣ - ΣΤΟΙΒΑΣ (Τα νέα στοιχεία προστίθενται στην αρχή της λίστας) Αφού µάθαµε πως µπορούµε να χειριστούµε τους δείκτες ας δούµε πως µπορούµε να τους χρησιµοποιήσουµε φτιάχνοντας µια στοίβα Ορίζω ένα δείκτη που θα δείχνει σε ένα στοιχείο µιας στοίβας program dnmiourgia_listas_stoivas; uses wincrt; type a = ^stoixeio; stoixeio = record data : integer; next : a; end; var arxn, trexwv : a; dedomena,k : integer; (* ηµιουργία αντίστροφης λίστας - στοίβας *) (* *) arxn:=nil; {1 Βάλε την αρχή της λιστας να δείχνει στο nil} writeln (' για ΤΕΛΟΣ δώσε 9999 '); write (' δώσε δεδοµένο για λίστα '); readln (dedomena); {2 Πάρε από το πληκτρολόγιο το δεδοµένο που θα βάλεις στη λίστα} while dedomena <> 9999 do new (trexwv); {3 Παραχώρησε µνήµη στη µεταβλητή που δείχνει ο τρέχων δείκτης} trexwv^data:=dedomena; {4 Βάλε στον τρέχων δείκτη το δεδοµένο που µόλις διάβασες} trexwv^next:=arxn; {5 Βάλε το δείκτη της µεταβλητής να δείχνει στην αρχή της λίστας} arxn:=trexwv; {6 Βάλε το δείκτη που δείχνει στην αρχή της λίστας να δείχνει εκεί που δείχνει ο τρέχων δείκτης} write ('νέο δεδοµένο '); {7 Επανέλαβε τα προηγούµενα βήµατα µέχρι να δωθεί 9999} readln(dedomena); end; (* while *) (* ΕΚΤΥΠΩΣΗ ΛΙΣΤΑΣ *) (* *) {Ξεκινάει από την αρχή της λίστας εµφανίζει στη οθόνη το δεδοµένο του πρώτου στοιχείου της} { και στη συνέχεια προχωράει στο δεδοµένο του επόµενου στοιχείου της λίστας} k:=1; new (trexwv); trexwv:=arxn; while trexwv <> nil do writeln(k,'ο στοιχείο είναι ',trexwv^data); trexwv:=trexwv^next; k:=k+1; end; {while} if k=1 then writeln('λίστα Α ΕΙΑ '); end ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 16 σηµειώσειςpascal
ΗΜΙΟΥΡΓΙΑ ΑΤΑΞΙΝΟΜΗΤΗΣ ΛΙΣΤΑΣ - ΟΥΡΑΣ (Τα νέα στοιχεία προστίθενται στο τέλος της λίστας) Αφού µάθαµε πως χειριζόµαστε τους δείκτες ας δούµε πως µπορούµε να τους χρησιµοποιή-σουµε φτιάχνοντας µια ουρά Ορίζω ένα δείκτη που θα δείχνει σε ένα στοιχείο µιας ουράς program dnmiourgia_listas_ouras; uses wincrt; type a = ^stoixeio; stoixeio = record data : integer; next : a; end; var arxn, telos, trexwv : a; dedomena, k : integer; (* ηµιουργία αταξινόµητης λίστας - ουράς *) (* ----------------------------------------------------- *) arxn:=nil; {1 Βάλε την αρχή της λιστας να δείχνει στο nil } telos:=nil; writeln (' για ΤΕΛΟΣ δώσε 9999 '); write (' δώσε δεδοµένο για λίστα '); readln (dedomena); {2 Πάρε από το πληκτρολόγιο το δεδοµένο που θα βάλεις στη λίστα} while dedomena <> 9999 do new (trexwv); {3 Παραχώρησε µνήµη στη µεταβλητή που δείχνει ο τρέχων δείκτης} trexwv^data:=dedomena; {4 Βάλε στον τρέχων δείκτη το δεδοµένο που µόλις διάβασες} trexwv^next:=nil; {5 Βάλε το δείκτη της µεταβλητής να δείχνει nil, στo τέλος της λίστας} if arxn = nil then {* Μόνο για την αρχή της λίστας} arxn:=trexwv; telos:=trexwv; end {χωρίς ερωτηµατικό} else telos^next:=trexwv; {6 Βάλε το δείκτη που δείχνει στο τέλος της λίστας να δείχνει εκεί που δείχνει ο τρέχων δείκτης Ετσι συνδέθηκε το νέο στοιχείο στο τέλος} telos:=trexwv; {7 Ενηµέρωσε το δείκτη του τέλους να δείχνει στο νέο τέλος} end; { if } write ('νέο δεδοµένο '); {8 Επανέλαβε τα προηγούµενα βήµατα µέχρι να δωθεί 9999} readln(dedomena); end; (* while *) (* ΕΚΤΥΠΩΣΗ ΛΙΣΤΑΣ *) {Ξεκινάει από την αρχή της λίστας εµφανίζει στη οθόνη το δεδοµένο του πρώτου στοιχείου της και { στη συνέχεια προχωράει στο δεδοµένο του επόµενου στοιχείου της λίστας} k:=1; new (trexwv); trexwv:=arxn; while trexwv <> nil do writeln(k,'ο στοιχείο είναι ',trexwv^data); trexwv:=trexwv^next; k:=k+1; end; {while} if k=1 then writeln('λίστα Α ΕΙΑ '); end ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 17 σηµειώσειςpascal
ΤΑΞΙΝΟΜΗΣΗ ΛΙΣΤΑΣ Το παρακάτω πρόγραµµα είναι συνέχεια του προηγουµένου (Τι καλά που είναι να χρησιµοποιούµε διδικασίες)και πάλι χρησιµοποιούµε µια µεταβλητή (endiamesos) για προσωρινή αποθήκευση δεδοµένων που θα αλλάξουν θέσηη µέθοδος που ακολουθείται είναι της φυσαλλίδαςακριβώς τα ίδια κάνω και για ταξινόµηση µια λίστας - στοίβας ή ουράς program dnmiourgia_tajinomisn_listas_ouras; uses wincrt; type a = ^stoixeio; stoixeio = record data : integer; next : a; end; var arxn, trexwv,t1,t2 : a; dedomena, k, endiamesos : integer; enalagi :boolean; (* ηµιουργία αταξινόµητης λίστας - ουράς *) (* *) (* ΤΑΞΙΝΟΜΗΣΗ ΛΙΣΤΑΣ - ΟΥΡΑΣ *) (* *) if arxn <> nil then repeat enalagi:=true; new(t1); new(t2); t1:=arxn; t2:=t1^next; while t1^next <> nil do if t1^data > t2^data then endiamesos:=t1^data; t1^data:=t2^data; t2^data:=endiamesos; enalagi:=false; end; {µε ερωτηµατικό } t1:=t1^next; t2:=t2^next; end; {while} (* ΕΚΤΥΠΩΣΗ ταξινοµηµένης ΛΙΣΤΑΣ *) (* *) k:=1; new (trexwv); trexwv:=arxn; writeln ('Εκτύπωση ταξινοµηµένης λίστας'); while trexwv <> nil do writeln(k,'ο στοιχείο είναι ',trexwv^data); trexwv:=trexwv^next; k:=k+1; end; {while} if k=1 then writeln('λίστα για ταξινόµηση Α ΕΙΑ '); end ΜΑΖΕΡΑΣ ΑΧΙΛΛΕΑΣ 18 σηµειώσειςpascal