Apertura e Chiusura di File

ModalitàDescrizione
"r"Lettura. Il file deve esistere.
"w"Scrittura. Crea o sovrascrive il file.
"a"Aggiunta. Scrive alla fine del file.
"r+"Lettura e scrittura. Il file deve esistere.
"w+"Lettura e scrittura. Crea o sovrascrive.
"rb", "wb"Modalità binaria (aggiunge b alla modalità).
CScrittura e lettura di file di testo
#include <stdio.h>
#include <stdlib.h>

int main() {
    // ===== SCRITTURA =====
    FILE *file = fopen("dati.txt", "w");
    if (file == NULL) {
        perror("Errore apertura file");
        return 1;
    }

    fprintf(file, "Nome: Mario Rossi\n");
    fprintf(file, "Età: 35\n");
    fprintf(file, "Città: Roma\n");
    fclose(file);
    printf("File scritto con successo.\n");

    // ===== LETTURA riga per riga =====
    file = fopen("dati.txt", "r");
    if (file == NULL) { perror("Errore"); return 1; }

    char linea[256];
    printf("\nContenuto del file:\n");
    while (fgets(linea, sizeof(linea), file) != NULL) {
        printf("  %s", linea);
    }
    fclose(file);

    // ===== LETTURA carattere per carattere =====
    file = fopen("dati.txt", "r");
    int c, num_char = 0;
    while ((c = fgetc(file)) != EOF) num_char++;
    fclose(file);
    printf("\nNumero di caratteri: %d\n", num_char);

    return 0;
}
Controlla sempre NULL! Se fopen() fallisce (file inesistente, permessi insufficienti), ritorna NULL. Usare un file NULL causa un crash. Controlla sempre il valore di ritorno.

File Binari — fread e fwrite

Per salvare struct direttamente su file senza convertirle in testo, usa la modalità binaria.

Cfwrite e fread con struct
#include <stdio.h>
#include <string.h>

typedef struct {
    int  id;
    char nome[30];
    double saldo;
} Conto;

int main() {
    // Scrivi struct su file binario
    Conto conti[] = {
        {1, "Mario Rossi",   1250.50},
        {2, "Anna Bianchi",  3400.00},
        {3, "Luigi Verdi",    820.75}
    };

    FILE *f = fopen("conti.bin", "wb");
    if (!f) { perror("Errore"); return 1; }
    fwrite(conti, sizeof(Conto), 3, f);
    fclose(f);
    printf("3 conti scritti.\n");

    // Leggi struct da file binario
    Conto letti[10];
    f = fopen("conti.bin", "rb");
    int n = fread(letti, sizeof(Conto), 10, f);
    fclose(f);

    printf("\nConti letti (%d):\n", n);
    for (int i = 0; i < n; i++) {
        printf("  ID %d | %-15s | %.2f EUR\n",
               letti[i].id, letti[i].nome, letti[i].saldo);
    }

    return 0;
}

Posizionamento — fseek e ftell

Cfseek, ftell, rewind
#include <stdio.h>

int main() {
    FILE *f = fopen("test.txt", "w");
    fprintf(f, "ABCDEFGHIJ");
    fclose(f);

    f = fopen("test.txt", "r");

    // ftell: posizione corrente (byte dall'inizio)
    printf("Posizione iniziale: %ld\n", ftell(f));

    fgetc(f); fgetc(f); fgetc(f);
    printf("Dopo 3 getc: %ld\n", ftell(f));

    // fseek(file, offset, da_dove)
    // SEEK_SET = dall'inizio, SEEK_CUR = da qui, SEEK_END = dalla fine
    fseek(f, 0, SEEK_SET);   // torna all'inizio
    printf("Dopo SEEK_SET(0): %ld, char: %c\n", ftell(f), fgetc(f));

    fseek(f, 5, SEEK_SET);   // vai al 5° byte
    printf("Dopo SEEK_SET(5): %ld, char: %c\n", ftell(f), fgetc(f));

    fseek(f, -3, SEEK_END);  // 3 caratteri prima della fine
    printf("Dopo SEEK_END(-3): %ld, char: %c\n", ftell(f), fgetc(f));

    // Dimensione del file
    fseek(f, 0, SEEK_END);
    long dimensione = ftell(f);
    printf("Dimensione file: %ld byte\n", dimensione);

    rewind(f);  // Equivalente a fseek(f, 0, SEEK_SET)
    fclose(f);
    return 0;
}
🏋️ Esercizi
Metti in pratica la gestione dei file.
1
Conta parole in un file
FacileFile testo

Scrivi un programma che legga un file di testo e conti: righe, parole e caratteri totali. Stampa anche la riga più lunga. (Simile a wc di Unix)

C
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
    char nomefile[100];
    printf("Nome del file: ");
    scanf("%s", nomefile);

    FILE *f = fopen(nomefile, "r");
    if (!f) { perror("Errore"); return 1; }

    char linea[1024], linea_piu_lunga[1024] = "";
    int righe = 0, parole = 0, caratteri = 0;

    while (fgets(linea, sizeof(linea), f)) {
        righe++;
        caratteri += strlen(linea);

        if (strlen(linea) > strlen(linea_piu_lunga))
            strcpy(linea_piu_lunga, linea);

        // Conta parole
        int in_parola = 0;
        for (int i = 0; linea[i]; i++) {
            if (isspace(linea[i])) in_parola = 0;
            else if (!in_parola) { parole++; in_parola = 1; }
        }
    }
    fclose(f);

    printf("Righe:    %d\n", righe);
    printf("Parole:   %d\n", parole);
    printf("Caratteri:%d\n", caratteri);
    printf("Riga più lunga: %s", linea_piu_lunga);
    return 0;
}
2
Rubrica su file
MedioFile + struct

Crea una rubrica con struct Contatto (nome, telefono, email). Implementa: aggiunta contatto (salva su file), caricamento da file, ricerca per nome, visualizzazione tutti i contatti.

C
#include <stdio.h>
#include <string.h>

#define FILE_RUBRICA "rubrica.txt"
#define MAX 100

typedef struct {
    char nome[50], telefono[20], email[60];
} Contatto;

void aggiungi(Contatto c) {
    FILE *f = fopen(FILE_RUBRICA, "a");
    if (!f) { perror("Errore"); return; }
    fprintf(f, "%s|%s|%s\n", c.nome, c.telefono, c.email);
    fclose(f);
    printf("Contatto salvato.\n");
}

int carica(Contatto rubrica[]) {
    FILE *f = fopen(FILE_RUBRICA, "r");
    if (!f) return 0;
    int n = 0;
    char linea[150];
    while (fgets(linea, sizeof(linea), f) && n < MAX) {
        linea[strcspn(linea, "\n")] = '\0';
        sscanf(linea, "%49[^|]|%19[^|]|%59[^\n]",
               rubrica[n].nome, rubrica[n].telefono, rubrica[n].email);
        n++;
    }
    fclose(f);
    return n;
}

int main() {
    int scelta;
    do {
        printf("\n1. Aggiungi  2. Cerca  3. Tutti  4. Esci\nScelta: ");
        scanf("%d", &scelta);
        if (scelta == 1) {
            Contatto c;
            printf("Nome: "); scanf("%49s", c.nome);
            printf("Tel:  "); scanf("%19s", c.telefono);
            printf("Email:"); scanf("%59s", c.email);
            aggiungi(c);
        } else if (scelta == 2) {
            char cerca[50];
            printf("Cerca: "); scanf("%49s", cerca);
            Contatto r[MAX]; int n = carica(r);
            int trovato = 0;
            for (int i=0; i<n; i++)
                if (strstr(r[i].nome, cerca)) {
                    printf("→ %s | %s | %s\n", r[i].nome, r[i].telefono, r[i].email);
                    trovato = 1;
                }
            if (!trovato) printf("Nessun risultato.\n");
        } else if (scelta == 3) {
            Contatto r[MAX]; int n = carica(r);
            for (int i=0; i<n; i++)
                printf("%d. %-15s %s %s\n", i+1, r[i].nome, r[i].telefono, r[i].email);
            if (!n) printf("Rubrica vuota.\n");
        }
    } while (scelta != 4);
    return 0;
}
3
Copia e confronto di file
Difficilefread/fwrite / file binari

Scrivi un programma che: 1) copi un file (sorgente → destinazione) usando fread/fwrite con buffer da 4096 byte, 2) verifichi che i due file siano identici confrontando byte per byte, 3) stampi la velocità in KB/s simulata (usa il numero di byte processati).

C
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define BUFFER 4096

long copia_file(const char *src, const char *dst) {
    FILE *in  = fopen(src, "rb");
    FILE *out = fopen(dst, "wb");
    if (!in || !out) { if(in) fclose(in); if(out) fclose(out); return -1; }

    unsigned char buf[BUFFER];
    long totale = 0;
    size_t n;
    while ((n = fread(buf, 1, BUFFER, in)) > 0) {
        fwrite(buf, 1, n, out);
        totale += n;
    }
    fclose(in); fclose(out);
    return totale;
}

int file_uguali(const char *a, const char *b) {
    FILE *fa = fopen(a, "rb"), *fb = fopen(b, "rb");
    if (!fa || !fb) { if(fa) fclose(fa); if(fb) fclose(fb); return 0; }

    int c1, c2, uguale = 1;
    while ((c1 = fgetc(fa)) != EOF) {
        c2 = fgetc(fb);
        if (c1 != c2) { uguale = 0; break; }
    }
    if (fgetc(fb) != EOF) uguale = 0;  // fb più lungo
    fclose(fa); fclose(fb);
    return uguale;
}

int main() {
    // Crea un file di test
    FILE *f = fopen("originale.txt", "w");
    for (int i = 0; i < 1000; i++) fprintf(f, "Riga %d: test\n", i);
    fclose(f);

    clock_t start = clock();
    long bytes = copia_file("originale.txt", "copia.txt");
    double secondi = (double)(clock()-start) / CLOCKS_PER_SEC;

    if (bytes < 0) { printf("Errore nella copia.\n"); return 1; }

    printf("Copiati: %ld byte in %.4f s\n", bytes, secondi);
    if (secondi > 0)
        printf("Velocità: %.1f KB/s\n", (bytes/1024.0)/secondi);

    printf("File identici? %s\n",
           file_uguali("originale.txt", "copia.txt") ? "Sì ✓" : "No ✗");
    return 0;
}