Περίληψη
Αυτό το μάθημα ανοίγει την έκτη ενότητα του κύκλου μαθημάτων, αφιερωμένη στα σύνθετα δεδομένα. Εξηγεί σε τι χρησιμεύει η ενότητα: να διδάξει πώς αναπαρίστανται συλλογές δεδομένων (ακολουθίες σταθερού και μεταβλητού μεγέθους, δισδιάστατοι πίνακες και εγγραφές) και πώς επεξεργάζονται με τους βασικούς αλγορίθμους, γραμμένους με το χέρι και παρμένους από τη βιβλιοθήκη, με εκτίμηση του κόστους τους· παρουσιάζει τα έξι μαθήματά της και το νήμα που τα ενώνει· θυμίζει όσα η ενότητα θεωρεί γνωστά, κυρίως τους βρόχους με αναλλοίωτη και τη μεταβίβαση με σταθερή αναφορά· διατυπώνει το πρόβλημα που λύνει η ενότητα, εκείνο ενός προγράμματος που πρέπει να φυλάξει δεδομένα των οποίων το πλήθος δεν γνωρίζει και που, γραμμένο με μεμονωμένες μεταβλητές, αποσιωπά όσα του περισσεύουν· προαναγγέλλει το κόστος ως δεύτερο μέτρο ενός αλγορίθμου, δίπλα στην ορθότητά του· και δείχνει πού οδηγεί, στις επόμενες ενότητες και στον κύκλο μαθημάτων Προγραμματισμός σε C++ II.
Μαθησιακοί στόχοι
- Να περιγράφει τη σειρά των περιεχομένων της ενότητας και να εξηγεί τι προσφέρει κάθε μάθημα στο επόμενο.
- Να θυμάται τους βρόχους, τις αναλλοίωτές τους και τη μεταβίβαση παραμέτρων (με τιμή, με αναφορά και με σταθερή αναφορά) και να τα επαναλαμβάνει, αν χρειάζεται.
- Να προαναγγέλλει, με ένα παράδειγμα, το κόστος ενός αλγορίθμου ως δεύτερο μέτρο της ποιότητάς του, δίπλα στην ορθότητά του.
- Να αναγνωρίζει τι αναμένεται να ξέρει να κάνει στο τέλος της ενότητας και να το διακρίνει από όσα θα μάθει στις επόμενες ενότητες.
Αρχική αξιολόγηση
Πριν διατρέξουμε την ενότητα, αξίζει να μετρήσουμε το σημείο εκκίνησης. Η αξιολόγηση αυτή είναι αυτοαξιολόγηση: δεν βαθμολογείται, και μοναδικός σκοπός της είναι να προσανατολίσει τη μελέτη. Οι τέσσερις πρώτες ερωτήσεις ελέγχουν όσα η ενότητα θεωρεί γνωστά: την αναλλοίωτη του βρόχου που αναζητά ένα μέγιστο, τον τρόπο μεταβίβασης μιας μεγάλης παραμέτρου, το πλήθος των γύρων δύο εμφωλευμένων βρόχων και την αριθμητική χωρίς πρόσημο. Οι έξι που ακολουθούν αγγίζουν, με τη σειρά των μαθημάτων, τις κεντρικές ιδέες της ενότητας: τους έγκυρους δείκτες μιας ακολουθίας, τη δημιουργία ενός διανύσματος, το πόσες φορές μπορεί ένα μέγεθος να διαιρεθεί στο μισό, την αναζήτηση σε ταξινομημένα δεδομένα, τον διπλό δείκτη ενός δισδιάστατου πίνακα και τον κίνδυνο να φυλάσσονται σε χωριστές συλλογές τα δεδομένα μιας ίδιας οντότητας. Κανείς δεν είναι υποχρεωμένος να τις απαντήσει σωστά ακόμη, και σε ορισμένες το «δεν το ξέρω ακόμη» είναι τίμια απάντηση: κάθε απάντηση, σωστή ή λανθασμένη, εξηγεί το ζήτημα και κατονομάζει το μάθημα που το πραγματεύεται. Οι ίδιες δεξιότητες μετρώνται ξανά στο τέλος, στο μάθημα της σύνθεσης.
Πριν ξεκινήσεις την ενότητα, μέτρησε το σημείο εκκίνησής σου. Είναι μια σύντομη αυτοαξιολόγηση: δεν βαθμολογείται και το αποτέλεσμα αποθηκεύεται μόνο στον περιηγητή σου.
Ερώτηση 1Από προηγούμενες ενότητεςΤο απόσπασμα
int largest{0}; int t{}; while (std::cin >> t) { if (t > largest) { largest = t; } }πρέπει να αφήσει στοlargestτη μεγαλύτερη από τις θερμοκρασίες που διαβάστηκαν. Με ποια είσοδο αποτυγχάνει;Ο πρώτος γύρος συγκρίνει το δεδομένο με το 0 και το φυλάει αν είναι θετικό: με ένα μόνο θετικό δεδομένο το αποτέλεσμα είναι σωστό. Αξίζει να ακολουθήσουμε το ίχνος πριν απαντήσουμε.Με το>ένα δεδομένο ίσο με το μέγιστο δεν το αντικαθιστά, αλλά το μέγιστο είναι ο ίδιος αριθμός: η επανάληψη δεν αλλάζει το αποτέλεσμα.Προδίδει ότι η αρχικοποίηση δεν ελέγχθηκε με την αναλλοίωτη: ένας σωστός βρόχος απαιτεί η αναλλοίωτη να ισχύει πριν από τον πρώτο γύρο.Η επιθυμητή αναλλοίωτη, «τοlargestείναι το μέγιστο όσων διαβάστηκαν ως τώρα», δεν ισχύει στην αρχή, γιατί πριν διαβαστεί οτιδήποτε δεν υπάρχει μέγιστο, και το αρχικό 0 υπερέχει κάθε αρνητικού δεδομένου. Διορθώνεται με αρχικοποίηση από το πρώτο δεδομένο, αφού ελεγχθεί ότι υπάρχει. Το μάθημα Διανύσματα κάνει το ίδιο σε μια αποθηκευμένη ακολουθία, και η βιβλιοθήκη το εκφράζει με τηstd::ranges::max, της οποίας η προσυνθήκη είναι ότι η ακολουθία δεν είναι κενή.Επανάληψη: Σχεδίαση σωστών βρόχων
Ερώτηση 2Από προηγούμενες ενότητεςΜια συνάρτηση υπολογίζει πόσα φωνήεντα έχει ένα κείμενο ενός εκατομμυρίου χαρακτήρων, αποθηκευμένο σε ένα
std::string, και δεν το τροποποιεί. Πώς είναι προτιμότερο να δηλωθεί η παράμετρός της;Η μεταβίβαση με τιμή αντιγράφει το εκατομμύριο χαρακτήρες σε κάθε κλήση: είναι σωστή, αλλά πληρώνει ένα κόστος που δεν προσφέρει τίποτα.Δεν αντιγράφει, αλλά επιτρέπει να τροποποιηθεί το κείμενο χωρίς λόγο και δεν δέχεται ούτε σταθερά ούτε προσωρινό αντικείμενο: συγχέει το «δεν αντιγράφω» με το «επιτρέπω την τροποποίηση».Ο τρόπος μεταβίβασης είναι μέρος της διεπαφής: η μεταβίβαση με τιμή υπόσχεται στη συνάρτηση ένα δικό της αντίγραφο, και το πρόγραμμα πρέπει να το φτιάξει.Η σταθερή αναφορά διαβάζει το κείμενο χωρίς να το αντιγράφει και χωρίς άδεια να το τροποποιήσει, και δέχεται επιπλέον ένα προσωρινό αντικείμενο. Στην ενότητα 6 η επιλογή αυτή γίνεται ο κανόνας: μια συνάρτηση που διαβάζει ένα διάνυσμα ενός εκατομμυρίου δεδομένων το δέχεται ωςconst std::vector<int>&, και το περιττό αντίγραφο γίνεται το συχνότερο σφάλμα κόστους.Επανάληψη: Παράμετροι και εμβέλεια
Ερώτηση 3Από προηγούμενες ενότητεςΠόσες φορές εκτελείται το
++countστοfor (int i{0}; i < 6; ++i) { for (int j{0}; j < i; ++j) { ++count; } };Σωστή απάντηση:
Ο εσωτερικός βρόχος κάνει 0 γύρους με , έναν με , και ούτω καθεξής ως 5 με : συνολικά , που είναι . Το μάθημα Το κόστος ενός αλγορίθμου γενικεύει τον λογαριασμό: δύο βρόχοι που διατρέχουν όλα τα ζεύγη από δεδομένα κάνουν γύρους, και αυτός ο αριθμός κρίνει αν ένας αλγόριθμος είναι χρήσιμος για ένα εκατομμύριο δεδομένα.Επανάληψη: Βρόχοι
Ερώτηση 4Από προηγούμενες ενότητεςΤι γράφει η
std::println("{}", 0u - 1);σε ένα σύστημα μεunsigned intτων 32 bit;Πιστεύει ότι ένας τύπος χωρίς πρόσημο δέχεται αρνητικούς.Πιστεύει ότι η αφαίρεση σταματά στη μικρότερη τιμή του τύπου· η αριθμητική χωρίς πρόσημο κάνει τον κύκλο, δεν κορέννυται.Συγχέει μια πιθανή προειδοποίηση με ένα σφάλμα: η έκφραση είναι έγκυρη και η τιμή της είναι ορισμένη.Η αριθμητική χωρίς πρόσημο είναι αριθμητική υπολοίπων: η αφαίρεση του 1 από το 0 κάνει τον κύκλο ως τη μεγαλύτερη τιμή του τύπου, . Η ενότητα 6 μετρά τα μεγέθη με τονstd::size_t, που επίσης είναι χωρίς πρόσημο, ώστε τοv.size() - 1με κενό διάνυσμα να μη δίνει , αλλά έναν τεράστιο αριθμό· το μάθημα Πίνακες σταθερού μεγέθους προειδοποιεί για αυτή την αφαίρεση, και το μάθημα Διανύσματα δείχνει τον βρόχο που εξαιτίας της βγαίνει εκτός ορίων.Επανάληψη: Οι ακέραιοι και η αναπαράστασή τους
Ερώτηση 5Σε μια ακολουθία στοιχείων αριθμημένων όπως στη C++, ποιοι δείκτες προσδιορίζουν ένα στοιχείο;
Αριθμεί από το ένα, όπως στην κοινή γλώσσα· στη C++, τοa[n]είναι ήδη έξω από την ακολουθία.Είναι το συχνότερο σφάλμα κατά ένα: μετρά δείκτες για στοιχεία.Είναι τίμια απάντηση: το μάθημα 6.1 το εξηγεί, μαζί με τον λόγο για τον οποίο μετράμε από το μηδέν.Ο δείκτης της C++ μετρά από το μηδέν, γιατί είναι η μετατόπιση από το πρώτο στοιχείο: το πρώτο είναι τοa[0]και το τελευταίο τοa[n - 1]. Η πρόσβαση με[]σε δείκτη έξω από αυτό το διάστημα είναι απροσδιόριστη συμπεριφορά, και το μάθημα Πίνακες σταθερού μεγέθους διδάσκει πώς αποδεικνύεται, με την αναλλοίωτη του βρόχου, ότι κάθε πρόσβαση είναι έγκυρη.Επανάληψη: Πίνακες σταθερού μεγέθους
Ερώτηση 6Τι περιέχει το
vμετά τοstd::vector<int> v(3, 7);;Διαβάζει τις παρενθέσεις σαν να ήταν άγκιστρα.Αντιστρέφει τον ρόλο των δύο αριθμών.Είναι τίμια απάντηση: το μάθημα 6.2 παρουσιάζει το διάνυσμα και τους τρόπους δημιουργίας του.Με παρενθέσεις, ο πρώτος αριθμός είναι το πλήθος και ο δεύτερος η τιμή κάθε στοιχείου· με άγκιστρα, τοstd::vector<int> v{3, 7};είναι ο κατάλογος των στοιχείων, το 3 και το 7. Το διάνυσμα είναι ο πρώτος τύπος του κύκλου μαθημάτων στον οποίο τα άγκιστρα και οι παρενθέσεις λένε διαφορετικά πράγματα, και το μάθημα Διανύσματα το δείχνει με ένα πρόγραμμα.Επανάληψη: Διανύσματα
Ερώτηση 7Πόσους γύρους κάνει το
for (int m{1024}; m > 1; m /= 2) { ... };Σωστή απάντηση:
Οι τιμές τουmστην αρχή κάθε γύρου είναι 1024, 512, 256, 128, 64, 32, 16, 8, 4 και 2: δέκα γύροι, γιατί , και το δέκα είναι . Ένας αλγόριθμος που μειώνει το πρόβλημά του στο μισό σε κάθε βήμα κάνει της τάξης των βημάτων, και το μάθημα Το κόστος ενός αλγορίθμου τον ονομάζει λογαριθμικό: με ένα δισεκατομμύριο δεδομένα του αρκούν περίπου τριάντα.Επανάληψη: Το κόστος ενός αλγορίθμου
Ερώτηση 8Ένας τηλεφωνικός κατάλογος έχει ένα εκατομμύριο ονόματα σε αλφαβητική σειρά. Για να βρούμε ένα, τον ανοίγουμε στη μέση, απορρίπτουμε το μισό όπου το όνομα δεν μπορεί να βρίσκεται, και επαναλαμβάνουμε με το άλλο. Πόσες φορές, το πολύ, πρέπει να τον ανοίξουμε;
Είναι ο λογαριασμός της αναζήτησης που εξετάζει τα ονόματα ένα προς ένα: χωρίς να αξιοποιηθεί η σειρά, κατά μέσο όρο διατρέχεται ο μισός κατάλογος.Είναι η τετραγωνική ρίζα του ενός εκατομμυρίου: συγχέει τη διαίρεση του κομματιού στο μισό με τη διαίρεσή του σε μπλοκ.Χρησιμοποιεί τον δεκαδικό λογάριθμο: κάθε άνοιγμα απορρίπτει το μισό, όχι τα εννέα δέκατα.Κάθε άνοιγμα μειώνει στο μισό το κομμάτι όπου μπορεί να βρίσκεται το όνομα, και το ξεπερνά το εκατομμύριο: μετά από είκοσι διχοτομήσεις μένει ένα μόνο όνομα. Είναι η δυαδική αναζήτηση του μαθήματος Αναζήτηση και ταξινόμηση, που λειτουργεί μόνο αν τα δεδομένα είναι ταξινομημένα και που αιτιολογείται με μια αναλλοίωτη.Επανάληψη: Αναζήτηση και ταξινόμηση
Ερώτηση 9Με
std::vector<std::vector<int>> t{{1, 2, 3}, {4, 5, 6}};, πόσο κάνουν ταt[1][0]καιt.size();Διαβάζει τον πρώτο δείκτη ως στήλη και μετρά τις στήλες αντί για τις γραμμές.Πιστεύει ότι τοsize()μετρά όλα τα κελιά του πίνακα.Είναι τίμια απάντηση: το μάθημα 6.5 παρουσιάζει τους δισδιάστατους πίνακες ως διανύσματα διανυσμάτων.Ένας δισδιάστατος πίνακας είναι μια ακολουθία γραμμών: τοt[1]είναι η δεύτερη γραμμή,{4, 5, 6}, και τοt[1][0]το πρώτο της στοιχείο. Τοt.size()μετρά τις γραμμές, όχι τα κελιά. Το μάθημα Δισδιάστατοι πίνακες καθιερώνει τη σύμβαση «πρώτα η γραμμή, μετά η στήλη».Επανάληψη: Δισδιάστατοι πίνακες
Ερώτηση 10Ένα πρόγραμμα φυλάει τα ονόματα μιας ομάδας σε ένα διάνυσμα και τους βαθμούς τους σε ένα άλλο, έτσι ώστε ο βαθμός
grades[i]να είναι εκείνος τουnames[i]. Αν ταξινομήσει μόνο το διάνυσμα των βαθμών, τι συμβαίνει;Για τον μεταγλωττιστή τα δύο διανύσματα είναι ανεξάρτητα: η σχέση υπάρχει μόνο στο μυαλό όποιου έγραψε το πρόγραμμα.Ο αλγόριθμος δέχεται ένα μόνο διάνυσμα και δεν γνωρίζει την ύπαρξη του άλλου.Κάθε πρόσβαση είναι έγκυρη και κάθε αποτέλεσμα είναι ορισμένο: το ελάττωμα είναι λογικό, και γι’ αυτό δεν το επισημαίνει κανένας από τους δύο ανιχνευτές του κύκλου μαθημάτων (ο ανιχνευτής σφαλμάτων μνήμης, AddressSanitizer, και ο ανιχνευτής απροσδιόριστης συμπεριφοράς, UndefinedBehaviorSanitizer).
Φόρτωση του περιεχομένου…
Ολοκληρώθηκε
Συνδεθείτε για να αποθηκεύσετε την πρόοδό σας