File di Testo in C

Apertura, Lettura di file testuali sequenziali

Perché l'I/O sui File?

  • Memorizzare dati permanentemente
  • Leggere file di configurazione
  • Elaborare grandi dataset
  • Registrare l'output del programma
  • Scambiare dati tra programmi

Il Puntatore FILE

In C, i file sono accessibili tramite un puntatore ad una struttura dati FILE

#include <stdio.h>

FILE *fp;
  • Definito in <stdio.h>
  • Funge da riferimento al file
  • Deve essere dichiarato e passato a tutte le funzioni che operano sul file

Aprire un File

La Funzione fopen()

FILE *fopen(const char *filename, const char *mode);
  • filename: Percorso del file
  • mode: Modalità di apertura del file
  • Valore ritorno: Puntatore FILE o NULL in caso di errore

Modalità di Apertura File

Modalità Descrizione
"r" Solo lettura (il file deve esistere)
"w" Solo scrittura (crea nuovo o tronca)
"a" Append (aggiunge alla fine del file)
"r+" Lettura e scrittura (il file deve esistere)
"w+" Lettura e scrittura (crea nuovo o tronca)

Aprire un File: Esempio

#include <stdio.h>

int main() {
    FILE *file;

    // Apre il file in lettura
    file = fopen("data.txt", "r");

    // Controlla se il file è stato aperto con successo
    if (file == NULL) {
        printf("Errore: Impossibile aprire il file\n");
        return 1;
    }

    printf("File aperto con successo!\n");

    // Non dimenticare di chiudere il file
    fclose(file);
    return 0;
}

Controllo degli Errori

Controlla sempre se fopen() ha avuto successo

FILE *file = fopen("input.txt", "r");

if (file == NULL) {
    perror("Errore nell'apertura del file");
    return 1;
}

perror() stampa un messaggio di errore descrittivo

Leggere i File

Approcci Multipli

  • fgets() - Legge una riga alla volta
  • fscanf() - Legge input formattato
  • fread() - Legge dati binari

Leggere con fgets()

Ideale per la Lettura Riga per Riga

char *fgets(char *str, int n, FILE *stream);
  • str: Buffer per memorizzare la riga
  • n: Numero massimo di caratteri da leggere
  • stream: Puntatore FILE
  • Ritorna: str in caso di successo, NULL a EOF o errore

Comportamento di fgets()

  • Legge fino a:
    • Un carattere di nuova riga (\n)
    • Fine del file (EOF)
    • n-1 caratteri letti
  • Include il carattere di nuova riga nel buffer
  • Termina automaticamente la stringa con null
  • Ritorna NULL quando raggiunge la fine del file

Lettura Riga per Riga: Esempio

#include <stdio.h>
#define MAX_LINE 256

int main() {
    FILE *file;
    char line[MAX_LINE];

    file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("Errore nell'apertura del file");
        return 1;
    }

    // Legge e stampa ogni riga
    while (fgets(line, MAX_LINE, file) != NULL) {
        printf("%s", line);
    }

    fclose(file);
    return 0;
}

Esempio di Conteggio Righe

#include <stdio.h>
#define MAX_LINE 1024

int main() {
    FILE *file;
    char line[MAX_LINE];
    int count = 0;

    file = fopen("document.txt", "r");
    if (file == NULL) {
        perror("Errore nell'apertura del file");
        return 1;
    }

    while (fgets(line, MAX_LINE, file) != NULL) {
        count++;
    }

    printf("Totale righe: %d\n", count);
    fclose(file);
    return 0;
}

Chiudere un File

La Funzione fclose()

int fclose(FILE *stream);
  • Svuota tutti i dati bufferizzati
  • Rilascia le risorse di sistema
  • Ritorna 0 in caso di successo, EOF in caso di errore
  • Chiudi sempre i file quando hai finito!

Perché Chiudere i File?

  • Numero limitato di handle di file disponibili
  • Garantisce che i dati siano scritti su disco
  • Previene la corruzione dei dati
  • Libera le risorse di sistema
  • Buona pratica di programmazione

Chiudere File: Esempio

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");

    if (file == NULL) {
        perror("Errore nell'apertura del file");
        return 1;
    }

    // ... esegui operazioni sul file ...

    // Chiudi il file
    if (fclose(file) != 0) {
        perror("Errore nella chiusura del file");
        return 1;
    }

    printf("File chiuso con successo\n");
    return 0;
}

Buone Pratiche

  • Controlla sempre se fopen() ha successo
  • Chiudi sempre i file con fclose()
  • Usa dimensioni di buffer appropriate
  • Controlla i valori di ritorno delle operazioni sui file
  • Usa perror() per i messaggi di errore
  • Evita buffer overflow (usa dimensioni sicure)
  • Gestisci correttamente le condizioni di fine file

Errori Comuni

  • Dimenticare di controllare se il file si è aperto con successo
  • Non chiudere i file (perdita di risorse)
  • Buffer overflow causati da righe troppo lunghe
  • Percorsi di file non corretti
  • Modalità di apertura file errata
  • Usare il puntatore al file dopo averlo chiuso
  • Non gestire correttamente EOF

Esercizio Pratico

Scrivi un programma che:

  1. Apre un file di testo specificato dall'utente
  2. Lo legge riga per riga
  3. Stampa solo le righe che non iniziano con il '#'
  4. Conta e visualizza il totale delle corrispondenze
  5. Chiude correttamente il file

Riepilogo

Funzione Scopo
fopen() Apre un file, ritorna un puntatore FILE
fgets() Legge una riga dal file
fgetc() Legge un carattere dal file
fclose() Chiude il file e libera le risorse
perror() Stampa un messaggio di errore

Grazie!

Domande?

Usa i tasti freccia o spazio per navigare
Premi ESC per la panoramica