Vai al contenuto
Topos Uranos

Riepilogo

Il testo è il dato più frequente di un programma: nomi, messaggi, righe di un file, comandi di un utente. Questa lezione lo tratta come ciò che è per il C++, una sequenza di caratteri con operazioni proprie. Presenta std::string, che si crea, si concatena, si confronta e si scorre come un vettore di char con mestiere di testo; le sue operazioni di ricerca e di estrazione (find, substr, starts_with, contains) e il valore std::string::npos, con cui find dice di non aver trovato nulla; std::string_view, la vista che osserva un testo senza copiarlo, e la condizione da cui dipende: che il testo osservato continui a esistere. Chiudono la lezione le stringhe C, per leggere codice altrui, e l’ordine in cui il C++ confronta e ordina le parole.

Obiettivi di apprendimento

  1. Usare le operazioni di std::string (size, +, find, substr, starts_with, contains) per risolvere problemi di testo.
  2. Interpretare il risultato di find e confrontarlo con std::string::npos, e prevedere che cosa accade se lo si tratta come un numero qualsiasi.
  3. Ricevere testo in una funzione come std::string_view e spiegare con un esempio perché una vista non deve sopravvivere alla stringa che osserva.
  4. Leggere codice con stringhe C e spiegarne le differenze rispetto a std::string: il terminatore nullo, la dimensione fissa e la somma di due letterali, che non compila.

La stringa std::string

Creare, concatenare, scorrere

La lezione Caratteri, booleani, conversioni e costanti ha presentato il carattere, char, come un numero piccolo che una tabella converte in lettera. Un testo è una successione di caratteri; se è così, può essere conservato in uno std::vector<char>, e ciò che la lezione Vettori ha insegnato sulle sequenze varrebbe per esso. Ora, al testo si chiedono operazioni che a una sequenza qualsiasi non si chiedono: attaccargli un altro testo, cercarvi una parola, estrarne un pezzo, scriverlo in una volta sola. Ne segue un tipo proprio, la stringa, std::string, dell’header <string>: un vettore di char con mestiere di testo.

Programma in C++
#include <format>#include <print>#include <string>​int main(){    const std::string first{"Ada"};    std::string greeting{"Ciao, " + first};    greeting += '.';    std::println("{} ({} caratteri)", greeting, greeting.size());    std::println("Primo «{}», ultimo «{}»", greeting[0], greeting.back());    int spaces{0};    for (const char c : greeting) {        if (c == ' ') {            ++spaces;        }    }    std::println("Spazi: {}", spaces);    const std::string code{std::format("{}-{:03}", "MAT", 7)};    std::println("{} {}", code, code == "MAT-007");}
Output
Ciao, Ada. (10 caratteri)Primo «C», ultimo «.»Spazi: 1MAT-007 true

La riga 7 crea una stringa a partire da un letterale. La 8 la concatena: l’operatore + tra una stringa e un letterale produce una stringa nuova con i caratteri di entrambi, uno dopo l’altro. La 9 aggiunge un carattere alla fine con +=, che ammette anche una stringa o un letterale. Il resto è ciò che già si sapeva dei vettori: size() conta i caratteri (10, perché anche la virgola, lo spazio e il punto lo sono), greeting[0] è il primo e back() l’ultimo, e il ciclo delle righe da 13 a 17 scorre la stringa carattere per carattere con la forma per intervallo della lezione Cicli. Come il vettore, una stringa ammette inoltre push_back, pop_back e empty, e la libreria di GCC 15, quando non si ottimizza, controlla i suoi indici con operator[] (con l’ottimizzazione, quel controllo scompare).

Le ultime due righe mantengono ciò che aveva annunciato la lezione Progettare con le funzioni. std::format, di <format>, riceve gli stessi segnaposto di std::println, con le stesse specifiche di formato ({:03} riempie con zeri fino a tre cifre), ma invece di scrivere il risultato lo restituisce come stringa: è il modo di costruire un testo che poi si conserva, si confronta o si passa a una funzione. E == confronta due stringhe per il loro contenuto: sono uguali se hanno la stessa dimensione e gli stessi caratteri nello stesso ordine. Pertanto code == "MAT-007" è true, benché il testo di sinistra sia stato costruito a pezzi e quello di destra sia un letterale.

Confrontare

Oltre a == e !=, le stringhe ammettono <, <=, > e >=, che le confrontano in ordine lessicografico, quello del dizionario: si percorrono le due in parallelo, e nella prima posizione in cui differiscono decide il carattere minore; se una si esaurisce prima senza alcuna differenza, la più corta è la minore. Così la stringa «casa» è minore di «cosa», perché 'a' < 'o' nella seconda posizione, e «mare» è minore di «marea», perché la prima è un prefisso della seconda. Gli operatori confrontano stringhe: tra due letterali scritti tra virgolette confrontano un’altra cosa, perché un letterale non è uno std::string ma un array, come si vedrà nella sezione sulle stringhe C. Quale carattere sia «minore» lo decide il suo codice, non l’alfabeto; l’ultima sezione della lezione mostra che cosa ne segue.