Μετάβαση στο περιεχόμενο
Topos Uranos

Περίληψη

Το κείμενο είναι το συχνότερο δεδομένο ενός προγράμματος: ονόματα, μηνύματα, γραμμές ενός αρχείου, εντολές ενός χρήστη. Αυτό το μάθημα το αντιμετωπίζει ως αυτό που είναι για τη C++, μια ακολουθία χαρακτήρων με δικές της πράξεις. Παρουσιάζει την std::string, που δημιουργείται, συνενώνεται, συγκρίνεται και διατρέχεται σαν διάνυσμα από char φτιαγμένο για κείμενο· τις πράξεις αναζήτησης και εξαγωγής της (find, substr, starts_with, contains) και την τιμή std::string::npos, με την οποία η find λέει ότι δεν βρήκε τίποτα· την std::string_view, την όψη που παρατηρεί ένα κείμενο χωρίς να το αντιγράφει, και τη συνθήκη από την οποία εξαρτάται: το παρατηρούμενο κείμενο πρέπει να εξακολουθεί να υπάρχει. Κλείνουν το μάθημα οι συμβολοσειρές της C, για να διαβάζουμε ξένο κώδικα, και η σειρά με την οποία η C++ συγκρίνει και ταξινομεί τις λέξεις.

Μαθησιακοί στόχοι

  1. Να χρησιμοποιούνται οι πράξεις της std::string (size, +, find, substr, starts_with, contains) για την επίλυση προβλημάτων κειμένου.
  2. Να ερμηνεύεται το αποτέλεσμα της find και να συγκρίνεται με την std::string::npos, και να προβλέπεται τι συμβαίνει αν αντιμετωπιστεί ως ένας οποιοσδήποτε αριθμός.
  3. Να λαμβάνεται κείμενο σε μια συνάρτηση ως std::string_view και να εξηγείται με ένα παράδειγμα γιατί μια όψη δεν πρέπει να επιζεί της συμβολοσειράς που παρατηρεί.
  4. Να διαβάζεται κώδικας με συμβολοσειρές της C και να εξηγούνται οι διαφορές τους από την std::string: ο τερματικός μηδενικός χαρακτήρας, το σταθερό μέγεθος και το άθροισμα δύο σταθερών, που δεν μεταγλωττίζεται.

Η συμβολοσειρά std::string

Δημιουργία, συνένωση, διάσχιση

Το μάθημα Χαρακτήρες, λογικές τιμές, μετατροπές και σταθερές παρουσίασε τον χαρακτήρα, char, ως έναν μικρό αριθμό που ένας πίνακας μετατρέπει σε γράμμα. Ένα κείμενο είναι μια διαδοχή χαρακτήρων· αν αυτό ισχύει, μπορεί να αποθηκευτεί σε ένα std::vector<char>, και όσα δίδαξε το μάθημα Διανύσματα για τις ακολουθίες θα ίσχυαν και γι’ αυτό. Ωστόσο, από το κείμενο ζητούμε πράξεις που δεν ζητούμε από μια οποιαδήποτε ακολουθία: να του κολλήσουμε άλλο κείμενο, να βρούμε μέσα του μια λέξη, να εξαγάγουμε ένα κομμάτι, να το γράψουμε με μιας. Από αυτό προκύπτει ένας δικός του τύπος, η συμβολοσειρά, std::string, από την κεφαλίδα <string>: ένα διάνυσμα από char φτιαγμένο για κείμενο.

Πρόγραμμα σε C++
#include <format>#include <print>#include <string>​int main(){    const std::string first{"Ada"};    std::string greeting{"Hola, " + first};    greeting += '.';    std::println("{} ({} χαρακτήρες)", greeting, greeting.size());    std::println("Πρώτος «{}», τελευταίος «{}»", greeting[0], greeting.back());    int spaces{0};    for (const char c : greeting) {        if (c == ' ') {            ++spaces;        }    }    std::println("Κενά: {}", spaces);    const std::string code{std::format("{}-{:03}", "MAT", 7)};    std::println("{} {}", code, code == "MAT-007");}
Έξοδος
Hola, Ada. (10 χαρακτήρες)Πρώτος «H», τελευταίος «.»Κενά: 1MAT-007 true

Η γραμμή 7 δημιουργεί μια συμβολοσειρά από μια σταθερά. Η 8 τη συνενώνει με τον ισπανικό χαιρετισμό «Hola, » («Γεια σου, »): ο τελεστής + ανάμεσα σε μια συμβολοσειρά και μια σταθερά παράγει μια νέα συμβολοσειρά με τους χαρακτήρες και των δύο, τον έναν μετά τον άλλον. Η 9 προσθέτει έναν χαρακτήρα στο τέλος με τον +=, που δέχεται επίσης μια συμβολοσειρά ή μια σταθερά. Τα υπόλοιπα είναι όσα ήδη ξέραμε από τα διανύσματα: η size() μετρά τους χαρακτήρες (10, επειδή το κόμμα, το κενό και η τελεία είναι επίσης χαρακτήρες), το greeting[0] είναι ο πρώτος και η back() ο τελευταίος, και ο βρόχος των γραμμών 13 έως 17 διατρέχει τη συμβολοσειρά χαρακτήρα προς χαρακτήρα με τη μορφή εύρους του μαθήματος Βρόχοι. Όπως το διάνυσμα, μια συμβολοσειρά δέχεται επιπλέον τις push_back, pop_back και empty, και η βιβλιοθήκη του GCC 15, όταν δεν γίνεται βελτιστοποίηση, ελέγχει τους δείκτες της στον operator[] (με βελτιστοποίηση, ο έλεγχος αυτός εξαφανίζεται).

Οι δύο τελευταίες γραμμές εκπληρώνουν ό,τι προανήγγειλε το μάθημα Σχεδίαση με συναρτήσεις. Η std::format, από την <format>, δέχεται τις ίδιες θέσεις αντικατάστασης με την std::println, με τις ίδιες προδιαγραφές μορφής (το {:03} συμπληρώνει με μηδενικά ως τα τρία ψηφία), αλλά αντί να γράψει το αποτέλεσμα το επιστρέφει ως συμβολοσειρά: είναι ο τρόπος να κατασκευάσουμε ένα κείμενο που στη συνέχεια αποθηκεύεται, συγκρίνεται ή περνά σε μια συνάρτηση. Και ο == συγκρίνει δύο συμβολοσειρές με βάση το περιεχόμενό τους: είναι ίσες αν έχουν το ίδιο μέγεθος και τους ίδιους χαρακτήρες με την ίδια σειρά. Επομένως, το code == "MAT-007" είναι true, αν και το κείμενο στα αριστερά κατασκευάστηκε κομμάτι κομμάτι και το κείμενο στα δεξιά είναι σταθερά.

Σύγκριση

Εκτός από τους == και !=, οι συμβολοσειρές δέχονται τους <, <=, > και >=, που τις συγκρίνουν με τη λεξικογραφική διάταξη, τη σειρά του λεξικού: διατρέχονται και οι δύο παράλληλα, και στην πρώτη θέση όπου διαφέρουν αποφασίζει ο μικρότερος χαρακτήρας· αν η μία εξαντληθεί νωρίτερα χωρίς καμία διαφορά, μικρότερη είναι η κοντύτερη. Έτσι, η ισπανική λέξη «casa» είναι μικρότερη από την «cosa», επειδή 'a' < 'o' στη δεύτερη θέση, και η «mar» είναι μικρότερη από την «marea», επειδή η πρώτη είναι πρόθεμα της δεύτερης. Οι τελεστές συγκρίνουν συμβολοσειρές· ανάμεσα σε δύο σταθερές γραμμένες σε εισαγωγικά συγκρίνουν κάτι άλλο, επειδή μια σταθερά δεν είναι std::string αλλά πίνακας, όπως θα φανεί στην παράγραφο για τις συμβολοσειρές της C. Ποιος χαρακτήρας είναι «μικρότερος» το αποφασίζει ο κωδικός του, όχι το αλφάβητο· η τελευταία παράγραφος του μαθήματος δείχνει τι προκύπτει από αυτό.