Confrontare Stringhe in Linguaggio C
Una delle operazioni più comuni che si possono fare con le stringhe in linguaggio C è il confronto tra due stringhe.
Confrontare due stringhe significa stabilire se una stringa è minore, maggiore o uguale a un'altra stringa. In linguaggio C, per fare ciò si utilizzano le funzioni strcmp
e strncmp
che sono definite nella libreria string.h
.
In questa lezione vedremo come funzionano queste due funzioni e come sia possibile implementarle manualmente.
Ordine lessicografico e confronto di stringhe
Prima di poter vedere come sia possibile confrontare due stringhe in linguaggio C, è necessario soffermarsi su cosa vuol dire esattamente questa operazione.
Di solito, quando si parla di confrontare due sequenze di caratteri, o stringhe, si pensa immediatamente all'ordine alfabetico. Un po' come sono ordinate le parole all'interno di un dizionario.
In pratica, se abbiamo due parole, ad esempio albero e borsa, possiamo dire che albero è minore di borsa perché la lettera a, ossia la lettera iniziale di albero, viene prima in ordine alfabetico rispetto alla lettera b, che è la lettera iniziale di borsa:
Nel caso in cui, le parole che stiamo confrontando inizino con la stessa lettera, allora dobbiamo confrontare la seconda lettera, e così via, fino a quando non troviamo una differenza.
Ad esempio, se confrontiamo le parole albero e alba, possiamo dire che albero è maggiore di alba. Questo perché le due parole iniziano per le stesse tre lettere, a, l e b, ma la quarta lettera di albero è una e, mentre la quarta lettera di alba è una a. E dato che la lettera e viene dopo la lettera a in ordine alfabetico, possiamo dire che albero è maggiore di alba:
Da notare che il confronto alfabetico che abbiamo mostrato non dipende dalla lunghezza delle due parole. Infatti, se confrontiamo le parole albero e albergo, possiamo dire che albergo è minore di albero (infatti la lettera g viene prima della lettera o in ordine alfabetico), anche se la parola albergo è più lunga di albero.
In linguaggio C, così come nella stragrande maggioranza dei linguaggi di programmazione, il principio alla base del confronto tra stringhe è simile a quello che abbiamo appena descritto. Tuttavia, il confronto non viene fatto in base all'ordine alfabetico, ma in base all'ordine lessicografico.
Ordine lessicografico
Quando si confrontano due stringhe in linguaggio C si rispettano le seguenti regole:
- Una stringa
s1
è minore di una stringas2
se i primi caratteri dii s1
sono uguali ai primi caratteri dii s2
, ma il carattere dii+1 s1
è minore del carattere dii+1 s2
; - Una stringa
s1
è minore di una stringas2
se tutti i caratteri dis1
sono uguali ai primi caratteri dii s2
, mas1
è più corta dis2
.
Tralasciamo per un momento cosa voglia dire che un carattere è minore di un altro. Concentriamoci, adesso, sulle due regole che abbiamo appena elencato.
La prima regola, sostanzialmente, è una generalizzazione dell'ordinamento alfabetico che abbiamo visto prima. In pratica, si confrontano i caratteri delle due stringhe uno alla volta, partendo dal primo carattere. Se si trova una differenza tra due caratteri, allora si può dire quale delle due stringhe è maggiore.
La seconda regola, invece, riguarda il caso in cui una stringa rappresenta il prefisso dell'altra. In questo caso, la stringa più corta è minore di quella più lunga. Ad esempio, la stringa casa è minore di casale. Infatti, casale ha le stesse 4 lettere iniziali di casa, ma è più lunga.
Detto questo, adesso bisogna capire cosa voglia dire che un carattere è minore di un altro. In linguaggio C, i caratteri sono, essenzialmente, numeri. Ogni carattere è rappresentato da un numero intero, che è il suo codice ASCII. Quindi, quando si confrontano due caratteri, in realtà si confrontano i loro codici ASCII.
Del resto, una stringa in C non è composta da sole lettere, ma può contenere numeri, simboli e caratteri di controllo. In questo caso, il confronto tra due stringhe avviene confrontando i codici ASCII dei caratteri uno alla volta.
In base a ciò, il risultato è che il confronto tra due stringhe può portare a delle sorprese. Infatti, in ASCII i numeri sono rappresentati da codici che vanno da 48 a 57, mentre le lettere maiuscole sono rappresentate da codici che vanno da 65 a 90 e le lettere minuscole da 97 a 122. La conseguenza è che una cifra è minore di una lettera maiuscola, che a sua volta è minore di una lettera minuscola.
Ad esempio, la stringa 123ABC
è minore della stringa ABC
, perché il carattere 1
ha un codice ASCII minore del carattere A
.
Analogamente la stringa ABC
è minore della stringa abc
, perché il carattere A
ha un codice ASCII minore del carattere a
.
Vediamo altri esempi:
"Casa" < "casa"
"123" < "ABC"
"123" < "abc"
"CASA" < "casa"
"casale" > "casa"
"casa" == "casa"
In questo meccanismo rientrano anche i caratteri di punteggiatura. Ad esempio lo spazio ␣
ha un codice ASCII minore di qualsiasi lettera o cifra. Quindi, la stringa Casa mia
è minore della stringa Casale
.
Queste regole prendono, collettivamente, il nome di ordine lessicografico.
Ricapitolando:
Ordine lessicografico
In linguaggio C si usa l'ordine lessicografico per confrontare due stringhe. Una stringa s1
è minore di una stringa s2
se:
- I primi
caratteri dii s1
sono uguali ai primi caratteri dii s2
, ma il carattere dii+1 s1
è minore del carattere dii+1 s2
; - Tutti i caratteri di
s1
sono uguali ai primi caratteri dii s2
, mas1
è più corta dis2
.
Il confronto tra i singoli caratteri avviene confrontando i loro codici numerici ASCII.
Detto questo, possiamo passare a vedere come sia possibile confrontare due stringhe in linguaggio C.
Funzione strcmp
- Confronto di stringhe
In linguaggio C, per confrontare due stringhe si utilizza la funzione strcmp
che è definita nella libreria string.h
.
La funzione strcmp
accetta due stringhe come argomenti e restituisce un valore intero che rappresenta il risultato del confronto lessicografico tra le due stringhe.
La funzione strcmp
ha la seguente firma:
int strcmp(const char *s1, const char *s2);
Dove s1
e s2
sono le due stringhe da confrontare. Il risultato del confronto è restituito come valore intero:
- Se
s1
è minore dis2
, allora il valore restituito è minore di zero; - Se
s1
è maggiore dis2
, allora il valore restituito è maggiore di zero; - Se
s1
è uguale as2
, allora il valore restituito è zero.
Vediamo un esempio:
#include <stdio.h>
#include <string.h>
int main() {
char s1[] = "casa";
char s2[] = "casale";
int result = strcmp(s1, s2);
if (result < 0) {
printf("La stringa s1 è minore di s2\n");
} else if (result > 0) {
printf("La stringa s1 è maggiore di s2\n");
} else {
printf("Le due stringhe sono uguali\n");
}
return 0;
}
In questo esempio, la stringa s1
è minore di s2
, quindi il risultato del confronto è minore di zero. Di conseguenza, il programma stampa a video il messaggio La stringa s1 è minore di s2
.
Funzione strcmp
La funzione strcmp
è utilizzata per confrontare due stringhe in linguaggio C.
Essa è definita nella libreria string.h
:
#include <string.h>
La funzione strcmp
ha la seguente firma:
int strcmp(const char *s1, const char *s2);
Dove s1
e s2
sono le due stringhe da confrontare. Il risultato del confronto è restituito come valore intero:
- Se
s1
è minore dis2
, allora il valore restituito è minore di zero; - Se
s1
è maggiore dis2
, allora il valore restituito è maggiore di zero; - Se
s1
è uguale as2
, allora il valore restituito è zero.
Funzione strncmp
- Confronto di stringhe con prefisso
La funzione strcmp
confronta due stringhe per intero. Tuttavia, a volte può essere utile confrontare solo un prefisso delle due stringhe.
Per fare ciò, si può utilizzare la funzione strncmp
che è definita nella libreria string.h
.
La funzione strncmp
accetta tre argomenti: due stringhe e un intero che rappresenta il numero di caratteri da confrontare.
La funzione strncmp
ha la seguente firma:
int strncmp(const char *s1, const char *s2, size_t n);
Dove s1
e s2
sono le due stringhe da confrontare e n
è il numero di caratteri da confrontare.
Per il resto, la funzione è simile alla funzione strcmp
. Il risultato del confronto è restituito come valore intero e segue le stesse regole della funzione strcmp
.
Vediamo un esempio:
#include <stdio.h>
#include <string.h>
int main() {
char s1[] = "casa";
char s2[] = "casale";
/* Primo confronto: confronta solo i primi 4 caratteri */
int result1 = strncmp(s1, s2, 4);
if (result1 < 0) {
printf("I primi 4 caratteri di s1 sono minori dei primi 4 caratteri di s2\n");
} else if (result1 > 0) {
printf("I primi 4 caratteri di s1 sono maggiori dei primi 4 caratteri di s2\n");
} else {
printf("I primi 4 caratteri delle due stringhe sono uguali\n");
}
/* Secondo confronto: confronta solo i primi 5 caratteri */
int result2 = strncmp(s1, s2, 5);
if (result2 < 0) {
printf("I primi 5 caratteri di s1 sono minori dei primi 5 caratteri di s2\n");
} else if (result2 > 0) {
printf("I primi 5 caratteri di s1 sono maggiori dei primi 5 caratteri di s2\n");
} else {
printf("I primi 5 caratteri delle due stringhe sono uguali\n");
}
return 0;
}
In questo esempio, il programma effettua due confronti tra le stringhe s1
e s2
:
- Il primo confronto confronta solo i primi 4 caratteri delle due stringhe. Il risultato del confronto è uguale a zero in quanto i primi 4 caratteri delle due stringhe sono uguali. Il programma stampa a video il messaggio
I primi 4 caratteri delle due stringhe sono uguali
. - Il secondo confronto confronta i primi 5 caratteri delle due stringhe. Il risultato del confronto è minore di zero in quanto
s1
è composta da soli 4 caratteri, mentres2
è composta da 6. Di conseguenza, il programma stampa a video il messaggioI primi 5 caratteri di s1 sono minori dei primi 5 caratteri di s2
.
Funzione strncmp
La funzione strncmp
è utilizzata per confrontare due stringhe in linguaggio C, considerando al più i primi n
caratteri.
Essa è definita nella libreria string.h
:
#include <string.h>
La funzione strncmp
ha la seguente firma:
int strncmp(const char *s1, const char *s2, size_t n);
Dove s1
e s2
sono le due stringhe da confrontare e n
è il numero di caratteri da confrontare. Il risultato del confronto è restituito come valore intero:
- Se i primi
n
caratteri dis1
sono minori dei primin
caratteri dis2
, allora il valore restituito è minore di zero; - Se i primi
n
caratteri dis1
sono maggiori dei primin
caratteri dis2
, allora il valore restituito è maggiore di zero; - Se i primi
n
caratteri dis1
sono uguali ai primin
caratteri dis2
, allora il valore restituito è zero.
Implementazione di strcmp
e strncmp
A livello didattico, è sempre interessante vedere come funzionano le funzioni standard di un linguaggio di programmazione. In questo caso, vediamo come potrebbe essere implementata la funzione strcmp
e la funzione strncmp
.
Partiamo da una possibile implementazione della funzione strcmp
che chiameremo mia_strcmp
:
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 |
|
L'implementazione è molto interessante. La funzione è divisa in due parti in quanto deve tener conto del caso in cui una stringa abbia una lunghezza minore dell'altra.
Nella prima parte, righe 6-15, la funzione confronta i caratteri delle due stringhe uno alla volta fintanto che i caratteri siano diversi dal terminatore, \0
, e non vi sia una differenza. Se si trova una differenza, allora la funzione restituisce un valore intero che rappresenta il risultato del confronto. Altrimenti, i puntatori vengono incrementati.
La seconda parte, righe 18-24, si raggiunge quando si esce dal ciclo while
, senza che sia stato restituito un valore tramite return
. Ciò significa che si è verificato uno dei seguenti casi:
- Entrambe le stringhe sono terminate. In questo caso, le due stringhe sono uguali e la funzione restituisce zero; Infatti, se ci fosse stata una differenza, sarebbe stata rilevata nel ciclo
while
; - La stringa
s1
è terminata, ma la stringas2
no. In questo caso, la stringas1
è minore dis2
e la funzione restituisce un valore minore di zero; - La stringa
s2
è terminata, ma la stringas1
no. In questo caso, la stringas1
è maggiore dis2
e la funzione restituisce un valore maggiore di zero.
Da notare che la differenza tra i caratteri, alla righe 7 e 9, viene valutata in modo numerico, ossia semplicemente confrontando i codici ASCII dei due caratteri attraverso gli operatori di confronto <
e >
.
Passiamo ora all'implementazione della funzione strncmp
che chiameremo mia_strncmp
:
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 29 |
|
L'implementazione della funzione mia_strncmp
è simile a quella della funzione mia_strcmp
. La differenza principale è che la funzione mia_strncmp
confronta al più i primi n
caratteri delle due stringhe.
Per prima cosa, abbiamo aggiunto un contatore i
che tiene traccia del numero di caratteri confrontati. Questo contatore viene incrementato ad ogni iterazione del ciclo while
(riga 16). Abbiamo modificato la condizione del ciclo while
(riga 7) in modo che il ciclo termini quando si raggiunge il numero massimo di caratteri da confrontare, n
.
La seconda parte della funzione, righe 20-28, è simile a quella della funzione mia_strcmp
. Tuttavia, abbiamo aggiunto una condizione iniziale (riga 20) che controlla se il numero di caratteri confrontati è uguale a n
. In tal caso, la funzione restituisce zero, indipendentemente dal fatto che le due stringhe siano terminate o meno.
In Sintesi
Abbiamo studiato in questa lezione che:
- Il confronto tra due stringhe in linguaggio C avviene in base all'ordine lessicografico;
- L'ordine lessicografico si basa sul confronto dei singoli caratteri delle due stringhe, partendo dal primo carattere;
- Il confronto tra i singoli caratteri avviene confrontando i loro codici numerici ASCII;
- In base all'ordine lessicografico, una stringa
s1
è minore di una stringas2
se i primi caratteri dii s1
sono uguali ai primi caratteri dii s2
, ma il carattere dii+1 s1
è minore del carattere dii+1 s2
; - Per confrontare due stringhe in linguaggio C si utilizza la funzione
strcmp
che restituisce un valore intero che rappresenta il risultato del confronto; - La libreria
string.h
fornisce anche la funzionestrncmp
che permette di confrontare solo un prefisso delle due stringhe.
Inoltre, abbiamo visto come potrebbero essere implementate le funzioni strcmp
e strncmp
in linguaggio C.