File I/O
Lettura e scrittura di file in C: testo e binario, posizionamento e gestione errori.
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à). |
#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;
}
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.
#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
#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;
}
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)
#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;
}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.
#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;
}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).
#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;
}