8. Επαναληπτικές διαδικασίες
8.1 Δομή Για Έως Ανά
Ένα ιδιαίτερο κεφάλαιο στις γλώσσες προγραμματισμού είναι οι επαναληπτικές διαδικασίες. Είδαμε στο κεφάλαιο 5 για τη ροή εκτέλεσης προγράμματος και στο 6 είδαμε την Για εως {} να χρησιμοποιείται για να αλλάζουμε τον δείκτη σε πίνακα.Για ι=1 έως 100
Τύπωσε ι
Επόμενο ι
Για ι=1 έως 100 {
Τύπωσε ι
}
Βλέπουμε τις δυο μορφές της δομής ΓΙΑ με μπλοκ εντολών και χωρίς μπλοκ. Η μορφή με μπλοκ είναι η πιο γρήγορη.
Η μεταβλητή "ελέγχου" ι αλλάζει τιμές από ένα όριο έως ένα όριο. Το βήμα μπορούμε να το ορίσουμε:
Για ι=1 έως 100 ανά 2 {
Τύπωσε ι
}
Παρατηρήσεις:
- Μπορούμε να φωλιάσουμε όσα Για θέλουμε (πάνω από έναν αριθμό, π.χ. 8 είναι υπερβολικό ή κάτι ειδιδικό έχει ο κώδικας)
- Η Μ2000 δεν λογαριάζει το πρόσημο του βήματος, εκτός και αν τα όρια αρχής και τέλους είναι ίδια!
- Στο παράδειγμα παραπάνω η τελευταία τιμή εντός του μπλοκ είναι το 99 και εκτός το 101
- Αν έχουμε αρχή και τέλος το ίδιο νούμερο τότε το μπλοκ θα τρέξει μια φορά και απ΄το πρόσημο του βήματος θα έχουμε τιμή πάνω ή κάτω από το όριο όσο το βήμα
- Αν δεν δώσουμε βήμα θεωρείται το ένα αλλά σε περίπτωση ίδιου ορίου άνω και κάτω, δεν θα έχουμε αλλαγή μετά την έξοδο από το μπλοκ
- Το Για δουλεύει με Πραγματική (double), Ακέραια (ακέραια μεταβλητή με οποιοδήποτε τύπο εσωτερικά) και Μακρύ (32Bit) (στις νεότερες εκδόσεις δουλεύει και με τους υπόλοιπους τύπους όπως: Currency Λογιστικό, Decimal Αριθμό, Single Απλό (Πραγματικός μικρός) και Ακέραιο (16bit). Οι τοπικές μεταβλητές παίρνουν την πρώτη φορά τύπο, και μετά δεν αλλάζουν. (μέχρι να ξανά εκτελεστεί το τμήμα τους και να έρθει πάλι η πρώτη φορά...). Στο παρακάτω θα μας δώσει η Τύπος$() τιμή Decimal και το Μ=4 (τρεις επαναλήψεις). Αν ξεχάσουμε τα @ θα δώσει τιμή double και 2 (μία επανάληψη) γιατί τα δυο νούμερα σε double είναι ίσα (έχουν χαθεί τα μικρά νούμερα λόγω αποκοπής από το 16ο ή 17ο ψηφίο)! Ο Decimal έχει 27 ψηφία και με υποδιαστολή που παίζει παντού αλλά δεν έχει εκθετικό μέρος όπως ο Double. Ο Double έχει και Απειρο και -Απειρο. Δηλαδή είναι ο Double μεγαλύτερος από το Decimal αλλά με μικρότερη ακρίβεια. Ο Μ είναι double. Αν δώσουμε κάπου στο τέλος το ι=Μ τότε το Μ θα μετατραπεί σε Decimal και θα εκχωρηθεί στο ι αν γίνεται αλλιώς θα βγει λάθος! Η μετατροπή σε double δεν βγάζει ποτέ λάθος αλλά μπορεί να προκύψει λογικό λάθος όπως εδώ που η αναμενόμενη επανάληψη για τρεις φορές έγινε μόνο μία. Λογικό λάθος είναι ότι σχετίζεται με τον αλγόριθμο, και εδώ ο αλγόριθμος ήταν να κάνει επανάληψη για τρεις φορές (όσες θα κάναμε με το μυαλό μας, ή με χαρτί και μολύβι).
Μ=1
Για ι=12345678901234567890123456@ Έως 12345678901234567890123458@
Τύπωσε ι
Μ++
Επόμενο
Τύπωσε Τύπος$(ι), Μ
Για ι=12345678901234567890123456@ Έως 12345678901234567890123458@
Τύπωσε ι
Μ++
Επόμενο
Τύπωσε Τύπος$(ι), Μ
Ζ=Απειρο
Τύπωσε Τύπος$(Ζ)
Τύπωσε Τύπος$(Ζ)
- Χειρίζεται τα βήματα με δεκαδικούς με μια σχετική ακρίβεια ώστε να έχει σωστά βήματα.
- Η μεταβλητή μπορεί να αλλάξει μέσα στο μπλοκ αλλά η τιμή που θα πάρει την επόμενη φορά (στην άλλη επανάληψη ή στην έξοδο) θα είναι η σωστή, γιατί η μεταβλητή απλά ενημερώνεται κάθε φορά γίνεται επανάληψη. Έτσι ένα φωλιασμένο Για (δυο Για μαζί, με το ένα εσωτερικό) μπορεί να έχει την ίδια μεταβλητή ελέγχου (αν και πρακτικά δεν κερδίζουμε τίποτα).
- Η Για Επόμενο λειτουργεί με το σωρό ή στοίβα επιστροφών του αντικειμένου εκτέλεσης και είναι δυνατόν να χρησιμοποιηθεί σε νήμα σε σχέδιο νημάτων ταυτόχρονο. (για το λόγο αυτό σχεδιάστηκε).
- Η Για αντικείμενο {} διαφέρει γιατί δεν έχει = μετά το αναγνωριστικό μεταβλητής.
- Δείτε ειδικά για την έξοδο από τη Για παρακάτω
8.1 Έξοδος από επαναληπτική διαδικασία
Ενώ δεν μπορούμε να αλλάξουμε την μεταβλητή ελέγχου ώστε να αλλάξει τη επανάληψη, μπορούμε να σταματήσουμε την Για με Προς και έξοδο από το μπλοκ,
Για ι=1 έως 100 ανά 2 {
Πρός 30
030 Τύπωσε ι
Αν ι>30 τότε προς 300
}
Τέλος
300 Τύπωσε "Οκ"
Πρός 30
030 Τύπωσε ι
Αν ι>30 τότε προς 300
}
Τέλος
300 Τύπωσε "Οκ"
Στο παραπάνω πρόγραμμ η προς 30 δεν σταματάει το πρόγραμμα, ενώ η προς 300 κάνει έξοδο από την Για με Μπλοκ. Δεν ισχύει αυτό στη Για χωρίς μπλοκ.
Τύπωσε ι
Αν ι>30 τότε έξοδος Για
Επόμενο ι
Τύπωσε "Οκ"
Για την Για έως {}
Για ι=1 έως 100 ανά 2 {
Τύπωσε ι
Αν ι>30 τότε έξοδος
}
Τύπωσε "Οκ"
8.2 Επιλεκτική περιοχή επανάληψης
Αν ι>20 και ι<91 τότε Επόμενο ι
Τύπωσε ι
Αν ι=95 τότε { Διέκοψε }
Επόμενο ι
Τύπωσε "Οκ"
Στη Για έως {} έχουμε αυτό:
Για ι=1 έως 100 ανά 2 {
Αν ι>20 και ι<91 τότε συνέχισε
Τύπωσε ι
Αν ι=95 τότε { Διέκοψε }
}
Τύπωσε "Οκ"
Η εντολή συνέχισε επιστρέφει στον έλεγχο επανάληψης χωρίς να ολοκληρώσει το μπλοκ.
Στην πρώτη περίπτωση της Για χωρίς μπλοκ χρησιμοποιούμε την Επόμενο ι (αν και πρέπει να ξεκαθαρίσουμε εδώ ότι υπάρχει περίπτωση να νομίζει ο διερμηνευτής ότι τελείωσε η επανάληψη σε αυτό το σημείο (αν ποτέ δεν έχει δει το άλλο). Με την Για με μπλοκ δεν έχουμε θέμα!
Με αυτόν τον τρόπο μπορούμε να βγάλουμε εκτός κάποιες περιοχές τιμών χωρίς να αλλάξουμε τα όρια στην Για (που θα έπρεπε να γίνει πριν μπούμε στη Για) αλλά το κάνουμε μέσα στο μπλοκ και ενώ δείχνουμε εδώ σταθερές τιμές στην Αν, σε άλλη περίπτωση μπορεί να είναι μεταβλητές!
Επιπλέον δείχνουμε ότι η Διέκοψε ενώ διακόπτει μπλοκ μέχρι το τμήμα, στη περίπτωση του Για σταματάει σε αυτό (ακόμα και αν δεν έχει μπλοκ, και λειτουργεί σαν έξοδος από το Για)
8.3 Κατεύθυνση επανάληψης
ΠΡΟΣΟΧΗ: Εδώ υπάρχει διαφορά με τη ΓΛΩΣΣΑ του σχολείου.
Για ι=1 έως 100 ανά 2
Αν ι>20 και ι<91 τότε Επόμενο ι
Τύπωσε ι
Επόμενο ι
Τύπωσε "Οκ"
Για ι=100 έως 1 ανά 2
Αν ι>20 και ι<91 τότε Επόμενο ι
Τύπωσε ι
Επόμενο ι
Τύπωσε "Οκ"
Επίσης το πρόσημο του βήματος είναι σημαντικό μόνο αν η αρχή και το τέλος είναι το ίδιο νούμερο!
Στο παράδειγμα το πρόσημο στο βήμα θα αγνοηθεί
Για ι=1 έως 30 ανά -1 {
Τύπωσε ι
}
Τύπωσε ι \\ 31
Παρακάτω αν δώσουμε βήμα αρνητικό θα πάμε όσο λέει το βήμα, θα εκτελεστεί μια φορά το μπλοκ, θα δώσει 1 και μετά θα πάει στο μηδέν. Αν είχαμε δώσει 1 θα πήγαινε στο 2
Για ι=1 έως 1 ανά -1 {
Τύπωσε ι
}
Τύπωσε ι \\ 0
8.4 Ελάχιστη επανάληψη
Για ι=1 έως 10 ανά 0 {
Τύπωσε ι
}
Τύπωσε ι \\ 1
δίνει δυο φορές το 1
Για ι=1 έως 1 ανά 0 {
Τύπωσε ι
}
Τύπωσε ι \\ 1
Επίσης δίνει δυο φορές το 1
Αυτό δεν ισχύει αν αλλάξουμε τη συμπεριφορά της ΓΙΑ επειδή θέλουμε να τρέξουμε ένα πρόγραμμα σε BASIC. Η Θέσε διακόπτες μέσα σε τμήμα αλλάζει πρόσκαιρα την συμπεριφρά του διερμηνευτή μέχρι να τερματίσει το Περιβάλλον. Αν δώσουμε (χωρίς τη Θέσε) την εντολή στην κονσόλα για τον διακόπτη "FOR" δεν θα ισχύει καθολικά αλλά μόνο για το τρέχον περιβάλλον (αυτό που τρέχουμε). Αρχική συνθήκη "-FOR". Μπορούμε να έχουμε μια συντόμευση για το m2000.exe και εκεί να δώσουμε το διακόπτη +FOR ώστε στην εκκίνηση του περιβάλλοντος να έχουμε την αλλαγή που θέλουμε. Υπάρχουν αρκετοί διακόπτες. Δείτε την Έλεγχος (εντολή κονσόλας) που δίνει την κατάσταση των διακοπτών. Η εντολή Θέσε στέλνει ότι γράφουμε μέχρι το τέλος της γραμμής στη κονσόλα, χωρίς να φαίνεται (οπότε δεν βλέπουμε εκεί τοπικές μεταβλητές, αλλά διαβάζουμε τον ίδιο σωρό τιμών, αν χρειαστεί).
Θέσε Διακόπτες "+FOR"
Για ι=1 έως 0
Τύπωσε "Δεν θα εκτελεστεί"
Επόμενο ι
Τύπωσε "Τέλος"
Μπορεί κανείς να φτιάξει ένα Για στα μέτρα του:
Εδώ φτιάχνουμε μια συνάρτηση που κάνει αυτό ακριβώς. Η Συνάρτηση Για() παίρνει τρεις συναρτήσεις, η μια αλλάζει την μεταβλητή ελέγχου, η άλλη καλεί εντολές και η τρίτη ελέγχει το όριο στη μεταβλητή ελέγχου.
Συνάρτηση Για {
Διάβασε &α(), &σ(), &εντ()
Επανέλαβε {
Κάλεσε α()
Κάλεσε εντ()
} Μέχρι σ()
}
ι=10
Συνάρτηση ι_συν {
ι++
}
Συνάρτηση ι_σ {
=ι>100
}
Συνάρτηση ι_εντ {
Τύπωσε ι
}
Κάλεσε Για(οκν$(&ι_συν()), οκν$(&ι_σ()), οκν$(&ι_εντ())
Η πιο απλή προσομοίωση είναι αυτή:
ι=1
{
Αν ι>100 τότε έξοδος
Τυπωσε ι
ι++
Κυκλικά
}
Όμως δεν έχει την λειτουργικότητα της Για της Μ2000, και την ταχύτητά της. Όταν η Για εκτελείται ξέρει επακριβώς που είναι η μεταβλητή της για να αφήσει τη νέα τιμή, από την πραγματική "αθέατη" μεταβλητή ελέγχου. Σε κάθε άλλη περίπτωση χωρίς την Για πρέπει ο διερμηνευτής να αναζητεί την μεταβλητή ελέγχου όπως όλες τις μεταβλητές.
Δες {
Για ι=1 εως 100000
Επόμενο ι
}
Τύπωσε ι
Το παραπάνω εκτελείται πολύ γρήγορα αλλά προλαβαίνουμε με το Esc να το διακόψουμε. Η Δες συγκρατεί τη διακοπή και έτσι παίρνουμε με την τύπωσε το ι
Αυτό όμως δεν σταματάει με Esc,εκτός και αν θέσουμε τον διερμηνευτή σε ταχύτητα ΑΡΓΑ οπότε τότε πιάνει το Ctrl+C . Στις νεότερες εκδόσεις η ταχύτητα είναι μεγάλη οπότε το 100000 έγινε 10000000, και σταματάει με Ctrl+C. με οποιοδήποτε σύστημα ταχύτητας διαλέξουμε. Το γρήγορα ! και το γρήγορα δεν έχουν μεγάλη διαφορά στην εκτέλεση σε προγράμματα χωρίς νήματα ή σε προγράμματα που ελέγχουμε την ανανέωση οθόνης).
Θέσε Γρήγορα !
Σημ Θέσε Γρήγορα
Σημ Θέσε Αργά
Διαφυγή Όχι
Δες {
Για ι=1 εως 10000000
Επόμενο ι
}
Τύπωσε ι
Γενικά το Esc μπορεί να χρησιμοποιηθεί για να κόψει μια Για σε λειτουργία Αργά και Γρήγορα αλλά όχι σε Γρήγορα ! (Αυτό ισχύει, και στις νεότερες εκδόσεις)
To Ctrl+C δεν κόβει το Για ούτε στο Γρήγορα.
Π.χ. η Γρήγορα ! αφαιρεί τελείως την ανανέωση οθόνης σε τακτά διαστήματα και την αφήνει στον προγραμματιστή με την εντολή Ανανέωση. Η Αργά δίνει στο σύστημα χρόνο, αρα αφήνει άλλες διεργασίες να εκτελεστούν.
Ουσιαστικά αλλάζουμε το φορτίο του διερμηνευτή αφαιρόντας κάτι, όπως τον έλεγχο για το Esc στις Για. Πάντα με γνώμωνα να πετύχουμε καλύτερους χρόνους.
Για ι=1 έως 0
Τύπωσε "Δεν θα εκτελεστεί"
Επόμενο ι
Τύπωσε "Τέλος"
8.5 Προσομοίωση της Για
Μπορεί κανείς να φτιάξει ένα Για στα μέτρα του:
Εδώ φτιάχνουμε μια συνάρτηση που κάνει αυτό ακριβώς. Η Συνάρτηση Για() παίρνει τρεις συναρτήσεις, η μια αλλάζει την μεταβλητή ελέγχου, η άλλη καλεί εντολές και η τρίτη ελέγχει το όριο στη μεταβλητή ελέγχου.
Συνάρτηση Για {
Διάβασε &α(), &σ(), &εντ()
Επανέλαβε {
Κάλεσε α()
Κάλεσε εντ()
} Μέχρι σ()
}
ι=10
Συνάρτηση ι_συν {
ι++
}
Συνάρτηση ι_σ {
=ι>100
}
Συνάρτηση ι_εντ {
Τύπωσε ι
}
Κάλεσε Για(οκν$(&ι_συν()), οκν$(&ι_σ()), οκν$(&ι_εντ())
Η πιο απλή προσομοίωση είναι αυτή:
ι=1
{
Αν ι>100 τότε έξοδος
Τυπωσε ι
ι++
Κυκλικά
}
Όμως δεν έχει την λειτουργικότητα της Για της Μ2000, και την ταχύτητά της. Όταν η Για εκτελείται ξέρει επακριβώς που είναι η μεταβλητή της για να αφήσει τη νέα τιμή, από την πραγματική "αθέατη" μεταβλητή ελέγχου. Σε κάθε άλλη περίπτωση χωρίς την Για πρέπει ο διερμηνευτής να αναζητεί την μεταβλητή ελέγχου όπως όλες τις μεταβλητές.
8.6 Τερματισμός με μη κανονικό τρόπο.
Υπάρχει πάντα περίπτωση κάποιος να δώσει ένα μεγάλο αριθμό επαναλήψεων, ή γιατί έδωσε μεγάλο τελικό όριο, ή γιατί έδωσε πολύ μικρό βήμα:Δες {
Για ι=1 εως 100000
Επόμενο ι
}
Τύπωσε ι
Το παραπάνω εκτελείται πολύ γρήγορα αλλά προλαβαίνουμε με το Esc να το διακόψουμε. Η Δες συγκρατεί τη διακοπή και έτσι παίρνουμε με την τύπωσε το ι
Αυτό όμως δεν σταματάει με Esc,
Θέσε Γρήγορα !
Σημ Θέσε Γρήγορα
Σημ Θέσε Αργά
Διαφυγή Όχι
Δες {
Για ι=1 εως 10000000
Επόμενο ι
}
Τύπωσε ι
Γενικά το Esc μπορεί να χρησιμοποιηθεί για να κόψει μια Για σε λειτουργία Αργά και Γρήγορα αλλά όχι σε Γρήγορα ! (Αυτό ισχύει, και στις νεότερες εκδόσεις)
8.7 Αλλαγή ταχύτητας επαναλήψεων
Μέσα από τμήμα μπορούμε να αλλάξουμε "ταχύτητα" με τις Θέσε Αργα, Θέσε Γρήγορα και Θέσε Γρήγορα!Π.χ. η Γρήγορα ! αφαιρεί τελείως την ανανέωση οθόνης σε τακτά διαστήματα και την αφήνει στον προγραμματιστή με την εντολή Ανανέωση. Η Αργά δίνει στο σύστημα χρόνο, αρα αφήνει άλλες διεργασίες να εκτελεστούν.
Ουσιαστικά αλλάζουμε το φορτίο του διερμηνευτή αφαιρόντας κάτι, όπως τον έλεγχο για το Esc στις Για. Πάντα με γνώμωνα να πετύχουμε καλύτερους χρόνους.
8.8 Άλλες επαναλήψεις
Σε αυτό το κεφάλαιο δεν δείχνουμε τις δομές Επανάλαβε { } Μέχρι, Επανάλαβε { } Πάντα καθώς και την Ενώ { }, ούτε την Κάθε { } όπως και την Κύριο.Έργο {} γιατί τα έχουμε δει σε προηγούμενα κεφάλαια. (Υπάρχειη Επανάλαβε και η Επανέλαβε, το πρώτο σωστό είναι γραμματικά)Μια ενδιαφέρουσα επανάληψη με μέτρηση είναι αυτή με αναδρομή:
Θέσε Γρήγορα
Συνάρτηση Άλφα {
Διάβασε Α
\\ το από Συνάρτηση το έβαλα έτσι, αφού δεν το κοιτάει
\\ ο διερμηνευτής!
Αν Α<1 Τότε =0 : Έξοδος από Συνάρτηση
Τύπωσε Α
=Άλφα(Α-1)
}
Αναλυτής
Α= Άλφα(14500)
Τυπωσε Φόρτος
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου
You can feel free to write any suggestion, or idea on the subject.