02. Le stringhe

Il linguaggio C implementa le stringhe a partire dagli array di caratteri.

Di seguito è rappresentato un array di char di dimensione 11 contenente la stringa "ciao"

Notare la presenza della escape sequence \0 subito dopo la sequenza di caratteri ciao.

Con \0 si indica un particolare carattere non stampabile (similmente a \n). In particolare si fa riferimento al primo carattere della tabella ASCII, quello con codifica numerica 0, denominato null.

Questo particolare carattere si utilizza per delimitare, in un array di caratteri, la sequenza significativa, separandola dai restanti caratteri contenuti dell'array che non sono ritenuti significativi.

La stringa "ciao" ha lunghezza 4 ma, in realtà, è composta da 5 caratteri perché occorre considerare anche il delimitatore \0. Si dice anche che le stringhe sono sequenza di caratteri null terminate.

In C è possibile fare riferimento a stringhe costanti, delimitando una sequenza di caratteri con doppie virgolette: ad esempio "hello!" è una stringa costante di lunghezza 6, costituita da 7 caratteri (includendo il delimitatore \0).

E' possibile stampare una stringa mediante la funzione printf() specificando la sequenza speciale %s.

Mediante la funzione scanf(), mediante la sequenza speciale %s, è possibile acquisire in un array di caratteri una stringa da tastiera. La sequenza immessa da tastiera si intende terminata in corrispondenza del carattere spazio oppure dell'invio. Specificando un numero prima della s si precisa il numero massimo di caratteri da acquisire.

Poiché la sequenza di caratteri verrà acquisita nell'array come stringa, occorre tenere presente che verrà automaticamente aggiunto all'array il carattere \0.

E' possibile effettuare il confronto tra due stringhe tramite la funzione strcmp() che riceve come parametri due stringhe e restituisce il valore 0 se le stringhe sono uguali. Nel caso la funzione ritorni -1 si intende che la prima stringa è minore (in base all'ordinamento alfabetico) mentre se ritorna 1 si intende il contrario.

Per conoscere la lunghezza di una stringa si usa invece la funzione strlen(), che considera il numero di caratteri presenti nell'array fino al terminatore '\0 (escluso).

Per utilizzare le funzioni strcmp() e strlen()  occorre includere la libreria string.h.


Esempio 1


#include <stdio.h>

int main()

{

    char arr[10];

    arr[0] = 'c';

    arr[1] = 'i';

    arr[2] = 'a';

    arr[3] = 'o';

    arr[4] = '\0';

    printf("%s\n", arr);

    printf("%s\n", "come stai?");

    return 0;

}


Esempio 2


#include <stdio.h>

int main()

{

    char arr[]="Hello World";

    int len = strlen(arr);

    printf("%s\n", arr);

    printf("La stringa %s e' formata da %d caratteri (terminatore escluso)\n", arr, len);

    return 0;

}

In questo esempio l'istruzione char arr[]="Hello World"; definisce un array di 12 caratteri, pari alla lunghezza della stringa più un carattere per il terminatore '\0', e assegna un carattere a ciascuna cella dell'array.

Esempio 3


#include <stdio.h>

int main()

{

    char arr[11];

    printf("Inserire un testo di massimo 10 caratteri: ");

    scanf("%10s", arr);

    printf("Il testo acquisito e': <%s>\n", arr);

    return 0;

}

In questo esempio la funzione scanf() acquisisce una stringa di massimo 10 caratteri. Poiché si tratta di una stringa verrà aggiunto sempre il terminatore '\0'.

Nel caso si inseriscano più di 10 caratteri, quelli in eccesso verranno ignorati. In ogni caso il terminatore '\0' verrà inserito e pertanto al massimo saranno inseriti nell'array 11 caratteri. In considerazione di ciò la dichiarazione dell'array deve eccedere di uno il numero massimo di caratteri da leggere indicato nella scanf().

Esempio 4


#include <stdio.h>

int main()

{

    char arr0[]="Stringa predefinita";

    char arr1[100];

    int i;

    for (i=0; arr0[i]!='\0'; i++)

        arr1[i]=arr0[i];

    arr1[i]='\0';

    printf("arr1 = %s\n", arr1);

    return 0;

}

In questo esempio viene effettuata la copia carattere a carattere dall'array arr0 all'array arr1.

Esempio 5


#include <stdio.h>

#include <string.h>

int main()

{

    char testo1[65], testo2[65];

    int ret;


    printf("Inserire due parole separate da spazio:\n");

    scanf("%64s %64s", testo1, testo2);


    ret=strcmp(testo1, testo2);


    if (ret==0)

        printf("\nLe due parole inserite sono uguali\n");

    else if (ret<0)

        printf("\nLa prima parola precede in ordine alfabetico\n");

    else

        printf("\nLa seconda parola precede in ordine alfabetico\n");

    return 0;

}

In questo esempio sono acquisite due parole poste su una stessa riga o anche su due righe differenti. Ciascuna parola è inserita in un differente array.

Tramite la funzione strcmp() è stabilito quale parola precede in ordine alfabetico (come in un vocabolario).


Stringa con parole multiple

Nel caso si vogliano acquisire più parole che devono costituire una stessa stringa, come nel caso di un cognome composto (ad esempio Del Monte), si potrà imporre che il separatore sia il carattere di INVIO della tastiera. In questo caso la stringa sarà composta da tutte le parole presenti sulla riga. 

Per far ciò si può usare la sequenza speciale %[^\n] nella scanf(). Questa direttiva indica che devono essere considerati tutti i caratteri fino all'INVIO che però non verrà eliminato. Per eliminare anche il carattere INVIO, occorre aggiungere la direttiva %*c che prescrive di eliminare un carattere senza assegnarlo ad alcuna variabile.

La sequenza che andrà utilizzata nella scanf sarà quindi %[^n]%*c.

In alternativa alla sequenza %*c si può utilizzare la funzione fflsush(stdin) che elimina tutti i caratteri pendenti.

Esempio 6

#include <stdio.h>

#include <string.h>


int main()

{

    char nome[100], cognome[100];

    int len;


    printf("Inserire il nome (sono ammessi nomi composti): ");

    scanf("%[^\n]%*c", nome);

    printf("Inserire il cognome (sono ammessi cognomi composti): ");

    scanf("%[^\n]%*c", cognome);


    len = strlen(nome);

    printf("Il nome <%s> e' lungo %d\n", nome, len);

    len = strlen(cognome);

    printf("Il cognome <%s> e' lungo %d\n", cognome, len);

}


In questo esempio le scanf() consentono di acquisire nome e cognome composti, purché inseriti su righe separate.

Non è effettuato alcun controllo sul numero di caratteri acquisiti pertanto gli array dovranno essere ragionevolmente grandi per evitare sfondamenti.

Esempio 7

#include <stdio.h>

#include <string.h>


int main()

{

    char nome[16], cognome[16];

    int len;


    printf("Inserire il nome (sono ammessi nomi composti): ");

    scanf("%15[^\n]%", nome);

    fflush(stdin);

    printf("Inserire il cognome (sono ammessi cognomi composti): ");

    scanf("%15[^\n]%", cognome);

    fflush(stdin);


    len = strlen(nome);

    printf("Il nome <%s> e' lungo %d\n", nome, len);

    len = strlen(cognome);

    printf("Il cognome <%s> e' lungo %d\n", cognome, len);

}


Anche in questo esempio le scanf() consentono di acquisire nome e cognome composti, purché inseriti su righe separate.

A differenza del caso analizzato nell'esempio 6, nella scanf() è effettuato il controllo sul numero massimo di caratteri che si possono acquisire pertanto se il numero di caratteri che compongono il nome o il cognome composto eccede la dimensione massima, i caratteri eccedenti sono ignorati. 

Per eliminare i caratteri pendenti (che in questo caso possono essere più di uno) si usa la funzione fflush(stdin).

Notare che gli array nome e cognome sono definiti di 16 caratteri mentre il numero massimo di caratteri accettati dalla scanf() è di 15. Questo perché la sedicesima cella dell'array è riservata a contenere il terminatore '\0'.