Περίληψη
Το μάθημα Βρόχοι δίδαξε πώς γράφεται μια επανάληψη· αυτό διδάσκει πώς γράφεται σωστά και πώς ξέρουμε γιατί είναι σωστή. Ξεκινά από τα μοτίβα με τα οποία κατασκευάζεται η πλειονότητα των βρόχων (ο μετρητής, ο αθροιστής, το μέγιστο και το ελάχιστο, ο φρουρός και η σημαία), καθένα ορισμένο από ό,τι σημαίνει η μεταβλητή του μετά από κάθε γύρο. Αυτή η παρατήρηση οδηγεί στην κεντρική έννοια: την αναλλοίωτη, μια πρόταση για τις μεταβλητές που ισχύει πριν από τον πρώτο γύρο και μετά από κάθε γύρο, και που, μαζί με τη συνθήκη εξόδου, συνεπάγεται το αποτέλεσμα. Είναι μια επαγωγή στον αριθμό των γύρων, και με αυτήν ένας βρόχος σχεδιάζεται ανάποδα: πρώτα ό,τι πρέπει να ισχύει στο τέλος, έπειτα η αναλλοίωτη, τελευταίο το σώμα. Ο τερματισμός αιτιολογείται με τη φθίνουσα ποσότητα, που παρουσιάστηκε ήδη στο μάθημα Από το πρόβλημα στον αλγόριθμο, και το μάθημα δείχνει τρεις βρόχους που δεν τερματίζουν: έναν με πραγματική συνθήκη, έναν με μετρητή χωρίς πρόσημο και έναν του οποίου ο μετρητής με πρόσημο υπερχειλίζει, που είναι απροσδιόριστη συμπεριφορά. Κλείνει με την πρώτη επαφή με τον αποσφαλματωτή του Visual Studio Code, που σταματά το πρόγραμμα σε μια γραμμή και δείχνει τις μεταβλητές του γύρο προς γύρο.
Μαθησιακοί στόχοι
- Να αναγνωρίζει σε έναν βρόχο τα μοτίβα του μετρητή, του αθροιστή, του μεγίστου και του φρουρού, και να τα χρησιμοποιεί για να σχεδιάζει νέους βρόχους.
- Να διατυπώνει την αναλλοίωτη ενός απλού βρόχου και να επιβεβαιώνει ότι διατηρείται σε έναν οποιονδήποτε γύρο.
- Να αιτιολογεί τον τερματισμό ενός βρόχου με μια ακέραια ποσότητα που μειώνεται και είναι φραγμένη.
- Να παρακολουθεί την εκτέλεση ενός βρόχου με τον αποσφαλματωτή του Visual Studio Code, με ένα σημείο διακοπής και την προβολή των μεταβλητών.
Μοτίβα
Τι σημαίνει μια μεταβλητή
Οι περισσότεροι βρόχοι δεν επινοούνται: συναρμολογούνται από λίγα κομμάτια που επανέρχονται σε όλα τα προγράμματα. Κάθε κομμάτι είναι μια μεταβλητή με μια αρχικοποίηση πριν από τον βρόχο, μια ενημέρωση μέσα σε αυτόν και, κυρίως, μια σημασία που ισχύει μετά από κάθε γύρο. Το να γνωρίζει κανείς τα κομμάτια από τη σημασία τους, και όχι από τη μορφή τους, είναι αυτό που επιτρέπει να τα συνδυάζει χωρίς σφάλμα.
- Ένας μετρητής ισούται με το πόσα δεδομένα έχουν επεξεργαστεί (ή πόσα ικανοποιούν μια συνθήκη). Αρχικοποιείται με 0, επειδή πριν από τον πρώτο γύρο δεν έχει επεξεργαστεί κανένα, και ενημερώνεται με
++count, μόνο όταν υπάρχει κάτι να μετρηθεί. - Ένας αθροιστής ισούται με τον συνδυασμό των δεδομένων που έχουν επεξεργαστεί: το άθροισμά τους, το γινόμενό τους. Αρχικοποιείται με το ουδέτερο στοιχείο της πράξης (0 για το άθροισμα, 1 για το γινόμενο), επειδή το άθροισμα κανενός δεδομένου είναι 0 και το γινόμενο κανενός δεδομένου είναι 1.
- Ένα μέγιστο ισούται με το μεγαλύτερο από τα δεδομένα που έχουν επεξεργαστεί, και ένα ελάχιστο, με το μικρότερο. Το μέγιστο κανενός δεδομένου δεν υπάρχει: γι’ αυτό αρχικοποιείται με το πρώτο δεδομένο, και όχι με έναν αριθμό διαλεγμένο στην τύχη.
- Ένας φρουρός είναι μια τιμή της εισόδου που δεν είναι δεδομένο, αλλά το σήμα ότι τα δεδομένα τελείωσαν. Το μοτίβο απαιτεί μία ανάγνωση πριν από τον βρόχο και άλλη μία στο τέλος του σώματος, όπως έκανε το μάθημα Βρόχοι όταν άθροιζε μέχρι το μηδέν, ώστε η συνθήκη να εξετάζει κάθε τιμή πριν αυτή υποστεί επεξεργασία, και ο φρουρός να μη μετρηθεί ποτέ ως δεδομένο.
- Μια σημαία είναι ένα
boolπου δείχνει αν κάτι συνέβη έστω μία φορά ανάμεσα στα δεδομένα που έχουν επεξεργαστεί. Αρχικοποιείται μεfalseκαι γίνεταιtrueτην πρώτη φορά που συμβαίνει· κανένας μεταγενέστερος γύρος δεν την επαναφέρει σεfalse.
Ένα παράδειγμα με όλα τα κομμάτια
Ένα ημερολόγιο βροχής καταγράφει τα χιλιοστά που έπεσαν κάθε μέρα. Το πρόγραμμα διαβάζει πρώτα ένα κατώφλι, και έπειτα τις μετρήσεις αρκετών ημερών, που τελειώνουν με έναν αρνητικό αριθμό, ο οποίος δεν είναι δυνατή μέτρηση και χρησιμεύει ως φρουρός· γράφει πόσες μετρήσεις υπάρχουν, τον μέσο όρο τους, το μέγιστο, πόσες μέρες ξεπέρασαν το κατώφλι και αν υπήρξε κάποια μέρα χωρίς βροχή.
#include <iostream>#include <print>int main(){ double threshold{}; std::cin >> threshold; int count{0}; // μετρητής: μετρήσεις που επεξεργάστηκαν int aboveCount{0}; // μετρητής: μετρήσεις πάνω από το κατώφλι double total{0.0}; // αθροιστής: άθροισμα των μετρήσεων double largest{0.0}; // μέγιστο: έχει νόημα μόνο αν count > 0 bool dryDay{false}; // σημαία: υπήρξε μέρα χωρίς βροχή double value{}; std::cin >> value; while (std::cin && value >= 0.0) { if (count == 0 || value > largest) { largest = value; } ++count; total += value; if (value > threshold) { ++aboveCount; } if (value == 0.0) { dryDay = true; } std::cin >> value; } if (count == 0) { std::println("Δεν υπάρχουν μετρήσεις."); } else { std::println("Μετρήσεις: {}, μέσος όρος: {:.2f} mm", count, total / count); std::println("Μέγιστο: {:.1f} mm, μέρες πάνω από {:.1f} mm: {}", largest, threshold, aboveCount); std::println("Υπήρξαν μέρες χωρίς βροχή: {}", dryDay ? "ναι" : "όχι"); }}104.5 0 12.5 21.5 7.5 -1Μετρήσεις: 5, μέσος όρος: 9.20 mmΜέγιστο: 21.5 mm, μέρες πάνω από 10.0 mm: 2Υπήρξαν μέρες χωρίς βροχή: ναιΤέσσερις αποφάσεις αξίζουν σχόλιο. Η συνθήκη count == 0 || value > largest αρχικοποιεί το μέγιστο με το πρώτο δεδομένο χωρίς χωριστή ανάγνωση: στον πρώτο γύρο ο μετρητής είναι 0 και η ανάθεση γίνεται πάντα· στους υπόλοιπους, μόνο αν το δεδομένο ξεπερνά το μέγιστο. Η σύγκριση value == 0.0 είναι ακριβής, επειδή η τιμή διαβάστηκε και δεν υπολογίστηκε: το ψηφίο 0 μετατρέπεται στο ακριβές μηδέν, και η προειδοποίηση του μαθήματος Οι αριθμοί κινητής υποδιαστολής κατά του == αφορά αποτελέσματα πράξεων. Η συνθήκη του βρόχου περιλαμβάνει το std::cin, ώστε μια είσοδος που τελειώνει χωρίς φρουρό να τερματίζει κι αυτή τον βρόχο. Και ο μέσος όρος υπολογίζεται μόνο αν υπάρχουν μετρήσεις: με count ίσο με 0, το total / count θα ήταν , που στην κινητή υποδιαστολή δεν είναι σφάλμα, αλλά η τιμή «δεν είναι αριθμός», την οποία το πρόγραμμα θα έγραφε χωρίς προειδοποίηση.
Απόδειξη
Πριν από τον βρόχο: το κατώφλι είναι 10, οι μετρητές και ο αθροιστής είναι 0, η σημαία είναι ψευδής, και η πρώτη μέτρηση, 4.5, έχει ήδη διαβαστεί. Το μέγιστο είναι 0, αλλά αυτή η τιμή δεν σημαίνει τίποτα όσο το
countείναι 0.Πρώτος γύρος: το
countείναι 0, οπότε το 4.5 γίνεται το μέγιστο· ο μετρητής ανεβαίνει στο 1 και το σύνολο στο 4.5. Διαβάζεται το 0.Δεύτερος γύρος: το 0 δεν ξεπερνά το μέγιστο, αλλά σηκώνει τη σημαία. Διαβάζεται το 12.5.
Τρίτος γύρος: το 12.5 είναι το νέο μέγιστο και ξεπερνά το κατώφλι: το
aboveCountανεβαίνει στο 1. Διαβάζεται το 21.5.Τέταρτος γύρος: το 21.5 είναι το νέο μέγιστο και ξεπερνά κι αυτό το κατώφλι. Διαβάζεται το 7.5.
Πέμπτος γύρος: το 7.5 δεν αλλάζει ούτε το μέγιστο ούτε το
aboveCount· το σύνολο φτάνει στο 46. Διαβάζεται το .Η συνθήκη εξετάζει το , που είναι αρνητικό: ο βρόχος τερματίζει χωρίς να το επεξεργαστεί. Ο μέσος όρος είναι .
Ας σημειωθεί ότι σε κάθε γραμμή του σχήματος κάθε μεταβλητή εκπληρώνει τη σημασία της ως προς τις μετρήσεις που έχουν επεξεργαστεί ως εκείνη τη στιγμή: το total είναι το άθροισμά τους, το largest το μέγιστό τους, το dryDay λέει αν υπήρξε ένα μηδέν ανάμεσά τους. Αυτή η ιδιότητα, που ισχύει μετά από κάθε γύρο, έχει όνομα.
Φόρτωση του περιεχομένου…
Ολοκληρώθηκε
Συνδεθείτε για να αποθηκεύσετε την πρόοδό σας