Funzioni per la Gestione dei Caratteri in Linguaggio C
Approfondiamo, in questa lezione, le funzioni per la gestione dei caratteri in Linguaggio C.
Vediamo come impiegare le funzioni scanf
e prinf
per leggere o scrivere caratteri. Introduciamo le funzioni getchar
e putchar
per leggere e scrivere caratteri da/su console. Infine, vediamo alcune delle funzioni della libreria ctype.h
per la manipolazione dei caratteri.
Lettura e Scrittura di caratteri con scanf
e printf
Le funzioni scanf
e printf
, già viste all'opera in precedenza, permettono di leggere e scrivere da/su console anche caratteri. Per fare ciò, è sufficiente utilizzare lo specificatore di formato %c
per la lettura e la scrittura di un singolo carattere.
Ad esempio:
char ch;
printf("Inserisci un carattere: ");
scanf("%c", &ch);
printf("Hai inserito il carattere: %c\n", ch);
La funzione scanf
, però, non salta i caratteri di spaziatura (come spazi, tabulazioni e ritorni a capo) e li considera come caratteri validi.
Per evitare questo problema e forzare la lettura di un singolo carattere saltando eventuali caratteri di spaziatura, possiamo aggiungere uno spazio davanti allo specificatore di formato %c
:
/* Legge un singolo carattere saltando eventuali caratteri di spaziatura */
scanf(" %c", &ch);
Il fatto che la funzione scanf
non salti i caratteri di spaziatura, può essere adoperato a nostro vantaggio. Infatti, può essere utilizzata per determinare, ad esempio, quando viene inserito un carattere di ritoro a capo.
Ad esempio, possiamo adoperare un ciclo do-while
per leggere un carattere alla volta fino a quando non viene inserito un carattere di ritorno a capo:
char ch;
do {
scanf("%c", &ch);
} while (ch != '\n');
Ricapitolando:
Specificatore di formato %c
per scanf
e printf
Lo specificatore di formato %c
permette di leggere e scrivere un singolo carattere con le funzioni scanf
e printf
.
Con la funzione scanf
, se anteposto da uno spazio, permette di saltare eventuali caratteri di spaziatura:
scanf(" %c", &ch);
Le funzioni getchar
e putchar
La libreria standard del C fornisce altri modi per leggere e scrivere caratteri da/su console. Questi metodi sono rappresentati dalle funzioni getchar
e putchar
.
La funzione putchar
prende in ingresso un carattere e lo stampa su console:
char ch = 'A';
putchar(ch);
La funzione getchar
legge un singolo carattere da console e lo restituisce come valore di ritorno:
char ch;
ch = getchar();
In verità, la funzione getchar
restituisce un intero int
anziché un char
. Il perché lo faccia lo vedremo nelle lezioni future. Per il momento prendiamolo come un dato di fatto.
In ogni caso, possiamo tranquillamente assegnare il valore restituito dalla funzione getchar
a una variabile di tipo char
.
Analogamente alla funzione scanf
, la funzione getchar
non salta i caratteri di spaziatura.
Funzione getchar
La funzione getchar
legge un singolo carattere da console e lo restituisce come valore di ritorno.
Il suo prototipo è il seguente:
int getchar(void);
Funzione putchar
La funzione putchar
stampa un singolo carattere su console.
Il suo prototipo è il seguente:
int putchar(int c);
Le funzioni getchar
e putchar
sono più performanti rispetto a scanf
e printf
per la lettura e la scrittura di singoli caratteri. Le motivazioni sono due:
-
In primo luogo sono funzioni più semplici e quindi più veloci.
Le funzioni
printf
escanf
sono molto complesse. Esse accettano in ingresso una stringa di formato proprio perché devono essere in grado di leggere e scrivere dati di diversi tipi. Questo le rende più lente rispetto agetchar
eputchar
, che invece lavorano solo con i caratteri. -
In secondo luogo,
getchar
eputchar
sono spesso implementate come macro e non come funzioni, il che le rende ancora più veloci. Studieremo le macro nelle prossime lezioni.
La funzione getchar
presenta, inoltre, un altro vantaggio rispetto alla funzione scanf
.
Il fatto che essa restituisca il valore letto, piuttosto che memorizzarlo in una variabile passata, permette di scrivere codice più idiomatico. Nel senso che possiamo scrivere codice più conciso e leggibile.
Ad esempio, riprendiamo l'esempio di sopra in cui abbiamo usato la funzione scanf
per leggere un singolo carattere alla volta fino a quando non viene inserito un carattere di ritorno a capo:
char ch;
do {
scanf("%c", &ch);
} while (ch != '\n');
Con la funzione getchar
possiamo scrivere lo stesso codice in modo più conciso:
char ch;
while ((ch = getchar()) != '\n');
In questo esempio, la variabile ch
viene inizializzata con il valore restituito dalla funzione getchar
. Il ciclo while
viene eseguito finché il valore di ch
è diverso dal carattere di ritorno a capo. Ma il corpo del ciclo è vuoto, perché tutto il lavoro è svolto dalla condizione del ciclo.
Possiamo anche ridurre il codice ulteriormente evitando l'uso di una variabile temporanea:
while (getchar() != '\n');
Possiamo usare un codice simile anche per implementare un ciclo che salti eventuali caratteri di spaziatura e restituisca il primo carattere non di spaziatura:
char ch;
while ((ch = getchar()) == ' ' || ch == '\t' || ch == '\n');
Quando il ciclo termina, la variabile ch
conterrà il primo carattere non di spaziatura.
Attenzione ad usare getchar
e scanf
insieme
Quando si usano, nello stesso programma, sia getchar
che scanf
bisogna prestare attenzione.
La funzione scanf
, infatti, tende a lasciare nell'input caratteri che ha soltanto letto ma non consumato. Questo può causare problemi quando si passa da scanf
a getchar
.
Prendiamo un esempio. Supponiamo di scrivere una porzione di codice che legge prima un intero con scanf
e poi un carattere con getchar
:
printf("Inserisci un intero: ");
scanf("%d", &n);
printf("Inserisci un carattere: ");
ch = getchar();
La prima chiamata a scanf
legge un intero da tastiera e si ferma alla pressione del tasto Invio. Il problema è che il tasto Invio lascia nel buffer di input un carattere di ritorno a capo. Il carattere di ritorno a capo non viene consumato.
Quindi, quando la funzione getchar
viene chiamata, essa legge il carattere di ritorno a capo lasciato da scanf
e non il carattere che l'utente ha inserito. Questo, ovviamente, non è il comportamento che ci aspettiamo.
Una possibile soluzione è quella di usare un ciclo, simile a quelli visti sopra, per consumare eventuali caratteri di spaziatura ed uscire dal ciclo solo quando viene inserito un carattere valido:
printf("Inserisci un intero: ");
scanf("%d", &n);
printf("Inserisci un carattere: ");
do {
ch = getchar();
} while (ch == ' ' || ch == '\t' || ch == '\n');
Funzioni per i char
La libreria standard del C fornisce tutta una serie di funzioni pronte per poter lavorare con i caratteri. Queste funzioni sono definite all'interno della libreria ctype.h
e sono utili per effettuare operazioni di confronto, conversione e manipolazione dei caratteri.
Vedremo l'elenco completo di queste funzioni nelle prossime lezioni. In questa lezione ne vedremo alcune tra le più importanti.
Convertire un carattere in maiuscolo o minuscolo
Per convertire un carattere in maiuscolo o minuscolo possiamo utilizzare le funzioni toupper()
e tolower()
rispettivamente.
Vediamo un esempio:
#include <stdio.h>
#include <ctype.h>
int main() {
char c = 'a';
char c_maiuscolo = toupper(c);
printf("Carattere iniziale: %c\n", c);
printf("Carattere in maiuscolo: %c\n", c_maiuscolo);
return 0;
}
Funzione toupper
La funzione toupper
converte un carattere in minuscolo in maiuscolo. Se il carattere passato come argomento è già in maiuscolo, la funzione restituirà lo stesso carattere.
Il suo prototipo è il seguente:
#include <ctype.h>
int toupper(int c);
Funzione tolower
La funzione tolower
converte un carattere in maiuscolo in minuscolo. Se il carattere passato come argomento è già in minuscolo, la funzione restituirà lo stesso carattere.
Il suo prototipo è il seguente:
#include <ctype.h>
int tolower(int c);
Verificare se un carattere è una lettera o un numero
Per verificare se un carattere è una lettera o un numero possiamo utilizzare le funzioni isalpha()
e isdigit()
rispettivamente.
Vediamo un esempio:
#include <stdio.h>
int main() {
char c;
printf("Inserisci un carattere: ");
scanf("%c", &c);
if (isalpha(c)) {
printf("Il carattere inserito è una lettera.\n");
} else if (isdigit(c)) {
printf("Il carattere inserito è un numero.\n");
} else {
printf("Il carattere inserito non è né una lettera né un numero.\n");
}
return 0;
}
Funzione isalpha
La funzione isalpha
verifica se il carattere passato come argomento è una lettera dell'alfabeto.
Il suo prototipo è il seguente:
#include <ctype.h>
int isalpha(int c);
Funzione isdigit
La funzione isdigit
verifica se il carattere passato come argomento è un numero.
Il suo prototipo è il seguente:
#include <ctype.h>
int isdigit(int c);
In Sintesi
In questa lezione abbiamo visto come gestire i caratteri attraverso funzioni della libreria standard del C.
In particolare:
- Abbiamo visto come leggere e scrivere caratteri con
scanf
eprintf
usando lo specificatore di formato%c
. - Abbiamo introdotto le funzioni
getchar
eputchar
per leggere e scrivere caratteri da/su console. - Abbiamo visto come convertire un carattere in maiuscolo o minuscolo con le funzioni
toupper
etolower
. - Abbiamo visto come verificare se un carattere è una lettera o un numero con le funzioni
isalpha
eisdigit
.