Υποπρογραμματα

Ξεκίνησε από Γιαννης Καραλης, 17 Φεβ 2003, 04:52:23 ΜΜ

« προηγούμενο - επόμενο »

Γιαννης Καραλης

Το βιβλιο δεν αναφερει τι γινεται με τα υποπρογραμματα και τους πινακες. γνωριζει κανεις πως πρεπει να γινεται η δηλωση τους σ'αυτα; ισχυει οτι και σε Pascal;

Δημήτρης Σλαβούδης

Γεια σας,

Πρώτη φορά χρησιμοποιώ το forum και ελπίζω να μας βοηθήσει όλους στην καλύτερη επικοινωνία μεταξύ μας που τόσο απαραίτητη είναι...

Μήπως ακούγεται τίποτα για εξαίρεση του 10ου Κ. γιατι
πολλά σχολεία δεν προλαβαίνουν την ύλη;

mxeg

#2
ΝΟΜΙΖΩ ΟΤΙ Ο ΤΡΟΠΟΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΔΗΛΩΝΟΝΤΑΙ ΑΝΑΦΕΡΕΤΑΙ ΣΤΟ ΤΕΤΡΑΔΙΟ ΤΟΥ ΜΑΘΗΤΗ ΚΑΙ ΕΙΝΑΙ ΑΡΚΕΤΟΣ
ΔΗΛΑΔΗ ΓΙΑ ΜΟΝΟΔΙΑΣΤΑΤΟ ΠΙΝΑΚΑ
Α[ΑΡΙΘΜΟΣ ΚΕΛΙΩΝ]
ΕΝΩ ΓΙΑ ΠΙΝΑΚΑ ΔΥΟ ΔΙΑΣΤΑΣΕΩΝ
Α[ΓΡΑΜΜΕΣ , ΣΤΗΛΕΣ]
ΝΟΜΙΖΩ ΑΥΤΟ ΕΙΝΑΙ ΑΡΚΕΤΟ ΓΙΑ ΤΑ ΠΑΙΔΙΑ  :)


Theofilos

Στο τετράδιο μαθητή σελ. 100

alkisg

#4
Επειδή έχω ξεκινήσει την υλοποίηση των υποπρογραμμάτων στον διερμηνευτή, θα ήθελα τις σκέψεις σας για κάποια θέματα, μήπως μου έχει ξεφύγει κάτι διαβάζοντας το βιβλίο.
Γράφω ένα παράδειγμα απλά για ευκολία στον σχολιασμό (Υ.Γ. για αυτόματο χρωματισμό του κώδικα στο στέκι αρκεί να γράφετε [glοssa]Εδώ μπαίνει το πρόγραμμα[/glοssa]):

[glossa]Πρόγραμμα Υποπρογράμματα
Μεταβλητές
  ακέραιες: α, β
Αρχή
  α ← 1
  β ← 2
  Κάλεσε Αντιμετάθεσε(α, β)
  Γράψε α, β
τέλος_προγράμματος

Διαδικασία Αντιμετάθεσε(γ, δ)
Μεταβλητές
  ακέραιες: γ, δ, προσωρινή
Αρχή
  προσωρινή ← γ
  γ ← δ
  δ ← προσωρινή
τέλος_διαδικασίας[/glossa]
Θέματα για συζήτηση:
  • Τα υποπρογράμματα μπαίνουν ΜΕΤΑ από το πρόγραμμα. (?)
  • Ο μηχανισμός μεταβίβασης παραμέτρων είναι με αντιγραφή κατά την είσοδο/έξοδο και όχι με αναφορά. Η μόνη διαφορά που θα βλέπουν οι χρήστες αν επιλεγεί ο μηχανισμός με αντιγραφή είναι κατά την βηματική εκτέλεση: όταν εκτελεστεί η εντολή γ <-- δ το γ εννοείται ότι θα γίνει 2, όμως το α του κυρίως προγράμματος θα γίνει κι αυτό αμέσως 2 ή θα γίνει 2 κατά το τέλος της διαδικασίας; Νομίζω ότι αυτό που περιγράφει το βιβλίο είναι ότι οι τιμές των τυπικών παραμέτρων αντιγράφονται στις πραγματικές παραμέτρους στο τέλος της διαδικασίας.
  • Μετά το τέλος_προγράμματος, τέλος_διαδικασίας ή τέλος_συνάρτησης μπαίνει το όνομα του προγράμματος/διαδικασίας/συνάρτησης ή όχι; Στο βιβλίο κατά κύριο λόγο δεν το βάζει ενώ στο τετράδιο μαθητή το βάζει. Εμένα μου φαίνεται άχρηστο, δηλαδή αν κάποιος γράψει λάθος το όνομα της διαδικασίας μετά το τέλος_διαδικασίας τι λάθος να του βγάλει ο διερμηνευτής; Να το ξαναγράψει σωστά; ;-)
Σχετικά με τις ασάφειες κατά το πέρασμα των παραμέτρων σκέφτηκα τα εξής:
  • Πρώτα λογικά πρέπει να γίνεται compile το πρόγραμμα, ώστε να εμφανίζονται πρώτα τα συντακτικά λάθη του προγράμματος και όχι των διαδικασιών. Όμως για να γίνει έλεγχος στον τύπο των παραμέτρων πρέπει πριν γίνει η μεταγλώττιση του προγράμματος να σαρωθούν οι δηλώσεις των διαδικασιών, μέχρι τουλάχιστον και το τμήμα "Μεταβλητές". Αυτό θα έχει το εξής αποτέλεσμα: πρώτα θα εμφανίζονται τα συντακτικά λάθη των ορισμών των διαδικασιών, μετά του κυρίως προγράμματος και τελικά των σωμάτων των διαδικασιών. Καμία καλύτερη ιδέα;
  • Οι παράμετροι θα είναι ΠΑΝΤΑ ΜΕ ΑΝΑΦΟΡΑ (εντάξει, copy-in/copy-out), αλλά μόνο όταν αυτό είναι δυνατό (έτσι κάνει και η basic αν δεν δηλωθούν byref/byvar). Δηλαδή η Αντιμετάθεσε του παραδείγματος δουλεύει κανονικά, αλλά αν καλεστεί ως "Κάλεσε Αντιμετάθεσε(1, 2)", δηλαδή με τιμές αντί για μεταβλητές, πάλι θα δουλεύει και φυσικά δεν θα αντιμεταθέτει το 1 με το 2 αλλά μόνο το γ με το δ. Με αυτόν τον τρόπο ΟΛΑ τα προγράμματα του βιβλίου θα μπορούν να εκτελεστούν, ακόμα και αυτά που έχουν αναδρομικές συναρτήσεις. Το μόνο κακό είναι ότι χρειάζεται λίγη προσοχή από την μεριά των καθηγητών ώστε να μην πειράζουν τις μεταβλητές που είναι μόνο για "είσοδο" στις διαδικασίες, δηλαδή σε μία "Κάλεσε Εκτύπωσε(α)" αν πειραχτεί το α μέσα στην Εκτύπωσε θα επιστραφεί στο κυρίως πρόγραμμα αλλαγμένο. Στην basic όταν θέλουμε να το αποφύγουμε αυτό κάνουμε "Κάλεσε Εκτύπωσε( (α) )", δηλαδή βάζουμε τις μεταβλητές μέσα σε παρένθεση ώστε να μην είναι πλέον μεταβλητές αλλά απλές εκφράσεις.
  • Όταν η παράμετρος μίας διαδικασίας είναι διαφορετικού τύπου τι γίνεται; Δηλαδή στην basic επιτρέπεται ακόμα και η "Κάλεσε Αντιμετάθεσε(1.4, 2.3)", με πραγματικές τυπικές παραμέτρους. Αλλά επιτρέπεται ακόμα και η "Κάλεσε Αντιμετάθεσε("12", "2.3") με ΑΛΦΑΡΙΘΜΗΤΙΚΕΣ παραμέτρους (περνιέται αυτόματα η ακέραια τιμή του αλφαριθμητικού)! Εγώ προτείνω όταν οι πραγματικές παράμετροι είναι διαφορετικού τύπου από τις τυπικές να εγείρεται συντακτικό λάθος, εκτός μόνο από την περίπτωση που σε τυπικές παραμέτρους πραγματικού τύπου περνιούνται πραγματικές παράμετροι ακέραιου τύπου, οπότε αυτό να επιτρέπεται αλλά φυσικά η μεταβίβαση να γίνεται με τιμή (να μην επιστρέφονται οι αλλαγές). Έτσι η ΑΠΟΛΥΤΗ_ΤΙΜΗ(πραγματικός) θα μπορεί να καλεστεί και με ακέραιο.
Ξέρω ότι μερικά από αυτά είναι δύσκολα σημεία και οι περισσότεροι δεν έχουν την όρεξη να μπουν σε τέτοιες λεπτομέρειες, αν όμως υπάρχουν διαφορετικές ιδέες/ερμηνίες του βιβλίου σε οποιοδήποτε σημείο θα ήθελα να τις ακούσω πριν προχωρήσω με την υλοποίηση.

ΝΙΚΟΣ ΧΑΤΖΗΓΙΑΝΝΑΚΗΣ

Αλκη συμφωνώ με την υλοποίηση που προτείνεις για το περασμα παραμέτρων. Δεδομένου οτι ειναι σαφές απο τα παραδείγματα του βιβλίου οτι το περασμα παραμέτρων γίνεται με αναφορά. Εγω θα προτιμούσα βέβαια να γίνεται με τιμή αλλα πρεπει να ακολουθηθεί το βιβλίο. Με τους πίνακες τι σκεφτεσε για το περασμα σε διαδικασία ? Πως θα δηλωνονται μεσα στη διαδικασία ? Θα δηλώνονται και οι διαστάσεις τους ?


alkisg

#6
Υποτίθεται ότι απλά «αναφέρονται» στη δήλωση της διαδικασίας και στη συνέχεια δηλώνονται κανονικά στο τμήμα μεταβλητών, π.χ.

[glossa]Διαδικασία ΠέραΒρέχει(εδώ, εκεί)
Μεταβλητές
  ακέραιες: εδώ
  πραγματικές: εκεί(100)
κτλ[/glossa]
Το μεγάλο κακό είναι ότι το βιβλίο περιγράφει copy-in/copy-out και όχι με αναφορά, οπότε αν χρειαστεί αναδρομή σε διαδικασία με παράμετρο πίνακα 100x100, τότε ΓΙΑ ΚΑΘΕ ΚΛΗΣΗ θα χρειάζεται μνήμη 100x100x16 bytes, το οποίο είναι ΥΠΕΡΒΟΛΙΚΟ!!! Έτσι το υλοποιώ τελικά, ελπίζω να μην χρειαστεί κανένα πρόγραμμα αναδρομή με μεγάλους πίνακες...

bugman

Σιγά βρε Άλκη μην δείξεις και τους παλμούς τους ρολογιού της CPU.(τι λέω τώρα!)

1. Φτιάχνεις διαδικασίες και πρέπει να δείχνεις μεταβλητές. Πολύ καλά! Δεν θα δείχνεις μεταβλητές που δεν λαμβάνουν χώρα σε μια διαδικασία! Θα δείχνεις τις τοπικές και τις εξωτερικές αν αυτές δηλώνονται στην ΓΛΩΣΣΑ. Διαφορετικά ξέχνα τες.
2. Αυτός που σκέφθηκε το πέρασμα τιμών ByRef είχε στον νού του την μικρή μνήμη της εποχής. Το πέρασμα με τιμή σημαίνει να έχεις χώρο να την βάλεις και τα 8bit συστήματα είχαν πολύ μικρό stack και γενικά μνήμη. Η BBC BASIC δούλευε με heap, έναν αντίθετο STACK που τον έβαζε στο τέλος του προγράμματος, έτσι πέρναγε τις τιμές ByVal. Ο Bill έφτιαξε την BASIC του αρχικά χωρίς υπορουτίνες (όπως τις έλεγε).  Η QuickBasic για να φανεί διαφορετική αλλά και να έχει πολύ γρήγορο χρόνο μετατροπής σε εκτελέσιμο κώδικα έβαζε byref τις παράμετρους των υπορουτινών.

3. Προτεινόμενη μέθοδος:
κατά την κλήση μιας διαδικασίας, βρίσκεις μία προς μια κάθε παράμετρο από την δήλωση της διαδικασίας. Για κάθε τιμή ή παράσταση που περνάμε, πρώτα ελέγχουμε αν είναι απλά μια τιμή ή μια παράσταση. Αν είναι παράσταση τότε (εδώ ε'ίναι το μυστικό) φτιάχνεις εαυτόματα μια μεταβλητή ΚΡΥΦΗ. Σε αυτήν βάζεις το αποτέλεσμα της παράστασης και κατόπιν δίνεις τον δείκτη σε αυτήν την κρυφή μεταβλητή ως τιμή της παραμέτρου.
Στην ουσία οι μεταβλητές στην διαδικασία είναι δείκτες σε μεταβλητές. (Αλλά δεν το ξέρει κανένας απ΄έξω)
Το πέρασμα μεταβλητής ByVal θα γίνει βάζοντας την μεταβλητή σε παρένθεση. Οπότε ο μετατροπέας (compiler) θα καταλάβει ότι έχει να κάνει με παράσταση και όχι με μια μεταβλητή. Στο τέλος της διαδικασίας όσες μεταβλητές περάσαμε ΒyRef θα έχουν την σωστή τιμή (δεν χρειάζεται copy). Επίσης οι αυτόματα δημιουργημένες μεταβλητές ( ο χώρος τους) θα αποδωθεί πίσω.

Ελπίζω να έδωσα την ιδέα!