Skip to content

Lettura e Scrittura di Testo

La libreria standard fornisce diverse funzioni specializzate per leggere e scrivere su stream orientati al testo (come la console o i file .txt).

  • fputc(c, stream): Scrive un singolo carattere.
  • fputs("Testo", stream): Scrive una stringa, ma a differenza di puts, non aggiunge il ritorno a capo (\n) automaticamente. Spetta a te inserirlo.
FILE *fp = fopen("saluti.txt", "w");
if (fp != NULL) {
fputs("Ciao mondo!\n", fp);
fclose(fp);
}

Se hai scritto dati in uno stream bufferizzato (es. in un file su disco) ma vuoi costringere il sistema a “svuotare il buffer” salvandoli istantaneamente fisicamente, usa:

fflush(fp);

Come imparato, la funzione gets() è bannata. Per leggere l’input dell’utente o un file riga per riga in totale sicurezza, usa fgets (File Get String).

char buffer[100];
// Legge fino a 99 caratteri (lasciando spazio al \0) dallo stream standard
fgets(buffer, sizeof(buffer), stdin);

fgets smette di leggere quando raggiunge il limite massimo, oppure quando incontra un “A Capo” (\n) o la Fine del File (EOF).

Esattamente come printf stampa sulla console, fprintf fa la stessa cosa ma dirige l’output in uno specifico FILE *. È perfetto per generare report testuali.

La funzione simmetrica, fscanf, permette di estrarre dati strutturati (interi, stringhe) analizzando una riga di testo usando i formati (%d, %s, ecc.). Inoltre offre dei modificatori avanzati chiamati Scanset:

  • %9s: Legge una stringa di massimo 9 caratteri senza spazi.
  • %99[^\n]: Legge tutto il testo (inclusi gli spazi) fino a quando non trova un a capo (che esclude tramite il caret ^), per un massimo di 99 caratteri.
int id;
char nome[50];
// Mettiamo che il file contenga: "1001 MarioRossi"
fscanf(fp, "%d %49s", &id, nome);

Best Practice: Parsing Robusto con fgets + sscanf

Section titled “Best Practice: Parsing Robusto con fgets + sscanf”

Un difetto di fscanf è che se il testo formattato non corrisponde a ciò che ci aspettiamo, lo stream si “incastra” lasciando caratteri spazzatura nel buffer. Per applicazioni robuste a livello industriale, la Best Practice assoluta è di leggere un’intera riga grezza in memoria con fgets(), e poi estrarre i dati da quella riga di memoria (non dal file!) usando sscanf().

È vitale controllare il valore di ritorno di sscanf. Questa funzione, infatti, restituisce un intero che indica il numero di campi analizzati con successo e assegnati alle variabili. Se ti aspetti due valori (un nome e un’età), devi assicurarti che sscanf restituisca esattamente 2.

💻 Esercizio Pratico: L’accoppiata Vincente (fgets + sscanf)

Section titled “💻 Esercizio Pratico: L’accoppiata Vincente (fgets + sscanf)”

Riceviamo in ingresso stdin una stringa formata da "NOME ETA". Usa prima fgets per leggere in modo sicuro la riga dal buffer, e poi usa un blocco if con sscanf per elaborare i due campi e controllare che il parsing abbia avuto successo.