Il linguaggio C++ ha conservato molto del linguaggio C, compresa la sua gestione delle stringhe in quanto indispensabile in alcuni contesti della programmazione. Il linguaggio C non mette a disposizione un tipo di dato specifico per le stringhe e per memorizzare una sequenza di caratteri alfanumerica utilizza un vettore di char. In C una stringa è un vettore di caratteri in cui l’ultimo elemento è un carattere terminatore (o di fine stringa), codificato con il carattere ASCII ‘\0’.
Si consideri la seguente dichiarazione in linguaggio C/C++:
1 |
char cognome[20] = "Rossi"; //dichiarazione con inizializzazione (1) |
Con l’istruzione (1) viene dichiarata la variabile ‘cognome’ come un vettore di 20 char che può essere utilizzato per memorizzare stringhe lunghe al massimo 19 caratteri. Un elemento del vettore, infatti, dovrà sempre essere riservato al carattere terminatore. In particolare, quella dichiarazione contiene anche l’inizializzazione della la variabile con l’assegnazione della stringa “Rossi”. Con questo tipo di inizializzazione il carattere terminatore viene aggiunto automaticamente. Si noti che dopo l’inizializzazione, le celle di indice superiore a 5 non sono “occupate” da caratteri, ma sono vuote solo teoricamente in quanto in realtà esse possono contenere dei valori casuali. Di qui l’importanza della presenza del carattere terminatore per capire dove finisce la stringa. Una variante rispetto all’inizializzazione utilizzata nella (1), consiste nello specificare i singoli elementi come per un qualsiasi vettore:
1 |
char cognome[20] = {'R', 'o', 's', 's', 'i', '\0'}; //(2) |
Errori tipici
1 2 |
string s = "Sono una stringa in stile C++"; scanf("%s", s); //ERRORE |
Programmando in linguaggio C++ bisogna ricordarsi che la funzione scanf() opera solo con le stringhe in stile C. Si tenga presente, inoltre, che essendo definita come un vettore di char, il nome di variabile di una stringa in stile C è una variabile di tipo puntatore ad un char e, quindi, essa contiene già l’indirizzo della stringa, pertanto:
1 2 3 |
char s[40] = "Sono una stringa in stile C"; scanf("%s", &s); //ERRORE scanf("%s", s); //CORRETTO |
Attenzione, l’assegnazione di una stringa ad un vettore di char è ammessa solo per l’inizializzazione del vettore nella sua dichiarazione (1), ma non è ammessa in nessun altra istruzione. Dopo la sua dichiarazione il vettore di char va trattato come un vettore a tutti gli effetti, eccezion fatta per alcune istruzioni evidenziate più avanti. Per cui non è possibile copiare una stringa in un’altra stringa con un’assegnazione:
1 2 3 |
char s1[10] = "testo 1"; char s1[10] = "testo 2"; s1 = s2 //ERRORE |
ma può essere fatto copiando un elemento per volta:
1 2 |
for(int i=0; s2[i]!='\0'; i++) s1[i] = s2[i]; |
Per la stessa ragione non è possibile confrontare due stringhe trattandole come due comuni variabili:
1 2 3 |
char s1[10] = "testo 1"; char s1[10] = "testo 2"; if (s1 == s2) //ERRORE |
Si ricordi che le stringhe in stile C sono dei vettori, per cui anche i confronti possono essere fatti solo fra gli elementi dei vettori. Solo a scopo didattico, per verificare l’uguaglianza tra s1 e s2 una possibile soluzione (che è da sconsigliare nei casi reali in cui vedremo è possibile utilizzare una opportuna funzione di libreria) potrebbe essere:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <stdio.h> int main() { char s1[10]; char s2[10]; bool isUguale = true; // si ipotizza che le due stringhe siano uguali printf("Inserisci la stringa n. 1\n"); scanf("%s", s1); printf("Inserisci la stringa n. 2\n"); scanf("%s", s2); //verifica se s1 e s2 sono uguali int i = 0; for(i=0; s1[i]!='\0'; i++) { if (s1[i]!=s2[i]) { isUguale = false; //s1 e s2 sono diverse break; } } //se è arrivato sul carattere terminatore di s1, verifica che sia così anche per s2 if (s1[i]=='\0' && s2[i]!='\0') isUguale = false; //s1 e s2 sono diverse if (isUguale) printf("Le due stringhe sono uguali"); else printf("Le due stringhe sono diverse"); return 0; } |
Nel programma precedente la verifica dell’uguaglianza fra le due stringhe avviene elemento per elemento, facendo una scansione dei due vettori di char. Ovviamente questo modo di operare già solo per fare un semplice confronto di uguaglianza sarebbe insostenibile, ed è per questo che per rendere più semplici le operazioni sulle stringhe in stile C conviene studiare la libreria C string.h, che contiene molte funzioni utili.
Eccezioni
Con le stringhe in stile C sono ammesse alcune eccezioni rispetto alla sintassi degli altri tipi di vettori. La prima eccezione è rappresentata dalla (1), già descritta sopra, le altre sono:
1 2 3 |
char cognome[20] = "Rossi"; cin >> cognome; //input da tastiera in C++ (AMMESSO) cout << cognome; //output sul monitor in C++ (AMMESSO) |
Sono delle eccezioni, perché tutti gli altri tipi di vettori diversi dal tipo char, infatti, possono essere caricati o visualizzati solo elemento per elemento.
Funzioni di libreria per la manipolazione delle C-string
La libreria standard del C dispone di funzioni molto utili per la gestione delle stringhe. Per poter utilizzare tali funzioni bisogna includere nel proprio file sorgente il file di libreria string.h:
1 |
#include <string.h> |
- FUNZIONE strcmp
1 |
strcmp(s1, s2); |
La funzione strcmp confronta due stringhe passate come parametro e restituisce al chiamante
- 0, se s1 == s2;
- un numero <0, se s1<s2;
- un numero >0, se s1>s2;
Esempio:
1 2 3 4 5 6 7 |
char s1[30], s2[30]; if(strcmp(s1, s2) == 0) printf("Le due stringhe sono uguali"); else if (strcmp(s1, s2) < 0) printf("%s1 < %s2", s1, s2); else printf("%s1 > %s2", s1, s2); |
- FUNZIONE strcpy
1 |
strcpy(destinazione, sorgente); |
La funzione strcpy copia la variabile stringa ‘sorgente’ nella variabile stringa ‘destinazione’ . La stringa ‘destinazione’ deve essere sufficientemente grande per accogliere tutti gli elementi della stringa ‘sorgente’.
Esempio:
1 2 3 4 |
char destinazione[30], sorgente[30]; printf("inserisci la stringa da copiare": "; scanf("%s", sorgente); strcpy(destinazione, sorgente); |
- FUNZIONE strlen
1 |
strlen(destinazione, sorgente); |
La funzione strlen restituisce al chiamante la lunghezza in caratteri della stringa passata come parametro.
Esempio:
1 2 3 4 5 6 |
char s[30]; int n; printf("Scrivi una parola: "); scanf("%s", s); n = strlen(s); printf("%s e' formata da %d caratteri.", s, n); |
- FUNZIONE strcat
1 |
strcat(s1, s2); |
La funzione strcat concatena le due stringhe passate come parametro.
Esempio:
1 2 3 4 5 6 7 8 9 10 |
char nome[15], cognome[15], nome_cognome[30]; int n; printf("Inserisci il tuo nome: "); scanf("%s", nome); printf("Inserisci il tuo cognome: "); scanf("%s", cognome); strcpy(nome_cognome, nome); strcat(nome_cognome, " "); strcat(nome_cognome, cognome); printf("%s", nome_cognome); |
Vettore di stringhe
La dichiarazione di un vettore di stringhe in stile C è analoga a quella dei vettori di tipo semplice:
1 |
char nomeVettore [N][S]; |
dove N è il numero di elementi di tipo stringa composti da S caratteri.
Esempio:
1 2 3 4 5 6 7 8 9 10 11 12 |
#define N 10 #define S 30 char v[N][S]; //carica il vettore composto da 10 stringhe, ciascuna con al massimo 29 caratteri for(i=0; i<N; i++) { printf("Inserisci una nuova stringa: "); scanf("%s", v[i]); } //visualizza il vettore di stringhe for(i=0; i<N; i++) { printf("%s\n", v); } |