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:

Definizione

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.

Definizione

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);
Definizione

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:

  1. In primo luogo sono funzioni più semplici e quindi più veloci.

    Le funzioni printf e scanf 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 a getchar e putchar, che invece lavorano solo con i caratteri.

  2. In secondo luogo, getchar e putchar 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.

Nota

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;
}
Definizione

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);
Definizione

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;
}
Definizione

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);
Definizione

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 e printf usando lo specificatore di formato %c.
  • Abbiamo introdotto le funzioni getchar e putchar per leggere e scrivere caratteri da/su console.
  • Abbiamo visto come convertire un carattere in maiuscolo o minuscolo con le funzioni toupper e tolower.
  • Abbiamo visto come verificare se un carattere è una lettera o un numero con le funzioni isalpha e isdigit.