Περίληψη
Ως εδώ, κάθε συλλογή του κύκλου μαθημάτων φύλαγε δεδομένα ενός μόνο τύπου: βαθμούς, αναστήματα, κελιά ενός δισδιάστατου πίνακα. Οι οντότητες ενός προβλήματος, αντίθετα, έχουν πολλά χαρακτηριστικά διαφορετικών τύπων: ένας φοιτητής έχει ένα όνομα και έναν βαθμό· ένα βιβλίο, έναν τίτλο, έναν συγγραφέα και ένα έτος. Το μάθημα αυτό παρουσιάζει την εγγραφή, τον σύνθετο τύπο που ορίζει ο ίδιος ο προγραμματιστής με struct για να συγκεντρώσει αυτά τα χαρακτηριστικά κάτω από ένα μόνο όνομα. Αρχίζει από τον λόγο ύπαρξης της εγγραφής, την ευθραυστότητα των παράλληλων διανυσμάτων· συνεχίζει με τον ορισμό ενός struct, τα πεδία του με αρχική τιμή και τη δημιουργία εγγραφών με άγκιστρα και με καθορισμένους αρχικοποιητές· έπειτα, τις εγγραφές ως παραμέτρους και ως αποτελέσματα συναρτήσεων· τα διανύσματα εγγραφών, που διατρέχονται με δομημένες δεσμεύσεις και ταξινομούνται και αναζητούνται με βάση ένα πεδίο, μαζί με το ζήτημα της ευσταθούς ταξινόμησης· και κλείνει με την τέχνη της μοντελοποίησης ενός προβλήματος με τύπους που αντανακλούν τον κόσμο του.
Μαθησιακοί στόχοι
- Να ορίζεται ένα
structμε πεδία και αρχικές τιμές, και να δημιουργούνται εγγραφές με αρχικοποίηση με άγκιστρα, και με καθορισμένους αρχικοποιητές. - Να γράφονται συναρτήσεις που δέχονται και επιστρέφουν εγγραφές, με επιλογή του τρόπου μεταβίβασης.
- Να ταξινομείται ένα διάνυσμα εγγραφών και να γίνεται αναζήτηση σε αυτό με βάση ένα πεδίο, με τις
std::ranges::sort,std::ranges::stable_sortκαιstd::ranges::findκαι μια προβολή, και να διακρίνεται μια ευσταθής ταξινόμηση από μια που δεν είναι. - Να μοντελοποιούνται με εγγραφές τα δεδομένα ενός προβλήματος και να αιτιολογείται ποια πεδία και ποιοι τύποι επιλέγονται.
Ομαδοποίηση δεδομένων
Παράλληλα διανύσματα
Ας υποθέσουμε ότι ένα πρόγραμμα πρέπει να φυλάει, για κάθε φοιτητή μιας ομάδας, το όνομά του, τον βαθμό του και την ηλικία του. Με όσα είδαμε ως το μάθημα Δισδιάστατοι πίνακες, η πρόχειρη λύση είναι τρία διανύσματα, ένα για κάθε χαρακτηριστικό, με τη σύμβαση ότι ο δείκτης δηλώνει το ίδιο πρόσωπο και στα τρία: names[i], grades[i] και ages[i]. Λέγονται παράλληλα διανύσματα. Ένας δισδιάστατος πίνακας δεν κάνει, γιατί τα κελιά του πρέπει να είναι όλα του ίδιου τύπου, και ένα όνομα δεν είναι αριθμός.
#include <algorithm>#include <cstddef>#include <print>#include <string>#include <vector>int main(){ const std::vector<std::string> names{"Άννα", "Λουίς", "Εύα"}; std::vector<int> grades{6, 4, 7}; const std::vector<int> ages{19, 22, 20}; std::ranges::sort(grades); for (std::size_t i{0}; i < names.size(); ++i) { std::println("{}: βαθμός {}, {} ετών", names[i], grades[i], ages[i]); }}Άννα: βαθμός 4, 19 ετώνΛουίς: βαθμός 6, 22 ετώνΕύα: βαθμός 7, 20 ετώνΤο πρόγραμμα ήθελε να ταξινομήσει τους φοιτητές κατά βαθμό, και ταξινόμησε μόνο τους βαθμούς. Μεταγλωττίζεται χωρίς προειδοποιήσεις, και ούτε ο ανιχνευτής σφαλμάτων μνήμης, AddressSanitizer, ούτε ο ανιχνευτής απροσδιόριστης συμπεριφοράς, UndefinedBehaviorSanitizer, έχουν κάτι να αναφέρουν· κι όμως, η έξοδός του είναι ψευδής: η Άννα είχε 6 και εμφανίζεται με 4. Η σύμβαση που ένωνε τα τρία διανύσματα δεν είναι γραμμένη πουθενά όπου να μπορεί να τη διαβάσει ο μεταγλωττιστής, ώστε τίποτα δεν εμποδίζει να παραβιαστεί. Από αυτό προκύπτει η ευθραυστότητα των παράλληλων διανυσμάτων: κάθε πράξη που μετακινεί, προσθέτει ή αφαιρεί ένα στοιχείο πρέπει να επαναλαμβάνεται, ίδια και με την ίδια σειρά, σε όλα τους· και αρκεί να ξεχαστεί ένα για να αλλοιωθούν τα δεδομένα σιωπηλά.
Τρία παράλληλα διανύσματα απέναντι σε ένα διάνυσμα από καρτέλες, καθεμιά με τα τρία δεδομένα ενός προσώπου.
Απόδειξη
Η στήλη 0 περιγράφει ένα πρόσωπο: τα
names[0],grades[0]καιages[0]είναι το όνομα, ο βαθμός και η ηλικία της Άννας. Ο δεσμός είναι μόνο ο δείκτης.Η
std::ranges::sort(grades)αναδιατάσσει μία μόνο γραμμή. Οι άλλες δύο δεν το μαθαίνουν: η στήλη 0 συνδυάζει τώρα το όνομα της Άννας, τον βαθμό του Λουίς και την ηλικία της Άννας, που δεν ανήκουν σε κανέναν.Η εναλλακτική: ένα μόνο διάνυσμα, του οποίου τα στοιχεία είναι καρτέλες. Κάθε καρτέλα περιέχει τα τρία δεδομένα ενός προσώπου, και ο δεσμός ανάμεσά τους δεν είναι πια μια σύμβαση για τους δείκτες, αλλά η ίδια η καρτέλα.
Η ταξινόμηση κατά βαθμό μετακινεί ολόκληρες καρτέλες: η καρτέλα του Λουίς περνά στην πρώτη θέση μαζί με το όνομα και την ηλικία του. Κανένα δεδομένο δεν μπορεί να αποχωριστεί από τα άλλα, γιατί η πράξη δεν τα βλέπει χωριστά.
Αν αυτό ισχύει, αυτό που ζητά το πρόβλημα είναι ένας τύπος του οποίου οι τιμές να είναι καρτέλες: μια τιμή που περιέχει ένα όνομα, έναν βαθμό και μια ηλικία, και που αντιγράφεται, μεταβιβάζεται σε μια συνάρτηση, φυλάγεται σε ένα διάνυσμα και ταξινομείται ως σύνολο. Η C++ δεν τον έχει έτοιμο, γιατί οι καρτέλες κάθε προβλήματος είναι διαφορετικές· επιτρέπει όμως στον προγραμματιστή να τον ορίσει. Αυτός ο τύπος είναι η εγγραφή.
Φόρτωση του περιεχομένου…
Ολοκληρώθηκε
Συνδεθείτε για να αποθηκεύσετε την πρόοδό σας