Scrittura, lettura e modifica di file di testo e binari con la libreria
La gestione dei file in C++ è fondamentale per salvare e recuperare dati da supporti esterni. Utilizzando la libreria <fstream>, è possibile eseguire operazioni di lettura, scrittura e modifica dei file in modo semplice ed efficiente.
🎯 Perché usare i file? Persistenza dei dati, condivisione di informazioni, backup e configurazioni dell'applicazione
1. Classi Principali della Libreria <fstream>
📌 Le tre classi fondamentali: Tutte ereditano da
<iostream>e offrono metodi per controllare il flusso dei dati
O ofstream
Stream di output per scrivere su file
Creazione e modifica file
ofstream fileOut("nome.txt");
I ifstream
Stream di input per leggere da file
Lettura e elaborazione dati
ifstream fileIn("nome.txt");
F fstream
Stream bidirezionale
Lettura e scrittura sullo stesso file
fstream fileIO("nome.txt");
2. Scrittura su File con ofstream
📌 Procedura di scrittura: Creazione oggetto → Apertura file → Verifica → Scrittura dati → Chiusura file
2.1 Esempio di Scrittura Base
#include <iostream>
#include <fstream>
using namespace std;
int main() {
// Creazione di un oggetto ofstream per scrivere su file
ofstream fileOut("dati.txt");
// Verifica dell'apertura del file
if (!fileOut) {
cerr << "Errore nell'apertura del file per la scrittura." << endl;
return 1;
}
// Scrittura di dati su file
fileOut << "Ciao, questo è un esempio di scrittura su file." << endl;
fileOut << "Linea 2: gestione dei file in C++." << endl;
// Chiusura del file
fileOut.close();
cout << "Dati scritti correttamente su 'dati.txt'." << endl;
return 0;
}
💡 Spiegazione: • Creazione oggetto:
ofstream fileOut("dati.txt")crea e apre il file • Controllo errori:if (!fileOut)verifica se l'apertura è riuscita • Scrittura: Si usa l'operatore<<come concout• Chiusura:close()libera le risorse
3. Lettura da File con ifstream
📌 Procedura di lettura: Apertura file → Verifica → Lettura riga per riga → Elaborazione → Chiusura
3.1 Esempio di Lettura Base
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream fileIn("dati.txt");
// Verifica dell'apertura del file
if (!fileIn) {
cerr << "Errore nell'apertura del file per la lettura." << endl;
return 1;
}
string riga;
// Lettura del file riga per riga
while (getline(fileIn, riga)) {
cout << riga << endl;
}
// Chiusura del file
fileIn.close();
return 0;
}
💡 Spiegazione: • getline(): Legge una riga intera fino al carattere di newline • Controllo fine file: Il ciclo while si ferma automaticamente a EOF • Alternative: Si può usare anche
fileIn >>per leggere parole singole
4. Operazioni Bidirezionali con fstream
🎭 Modalità di apertura: Combina diverse flag per controllare il comportamento del file
4.1 Flag di Apertura Comuni
I ios::in
Apertura in lettura
File deve esistere
O ios::out
Apertura in scrittura
Crea file se non esiste
T ios::trunc
Cancella contenuto esistente
File vuoto
A ios::app
Scrittura in append
Mantiene contenuto esistente
4.2 Esempio di Lettura e Scrittura
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Apertura del file in modalità lettura e scrittura
fstream file("dati_bidirezionale.txt", ios::in | ios::out | ios::trunc);
if (!file) {
cerr << "Errore nell'apertura del file." << endl;
return 1;
}
// Scrittura di dati sul file
file << "Linea 1: Dati iniziali." << endl;
file << "Linea 2: Continuazione dei dati." << endl;
// Per leggere il contenuto, è necessario riposizionare il cursore all'inizio
file.seekg(0);
string contenuto;
cout << "Contenuto del file:" << endl;
while (getline(file, contenuto)) {
cout << contenuto << endl;
}
file.close();
return 0;
}
💡 Spiegazione: • Combination flag:
ios::in | ios::out | ios::trunccombina più modalità • seekg(0): Riposiziona il cursore di lettura all'inizio del file • Operazioni miste: Possibile alternare lettura e scrittura sullo stesso file
5. Esercizio Pratico: Rubrica di Contatti
🎯 Obiettivo: Creare un programma che chieda all'utente di inserire contatti, salvi i dati in un file di testo e legga il file visualizzando tutti i contatti
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Contatto {
string nome;
string telefono;
};
int main() {
int n;
cout << "Quanti contatti vuoi inserire? ";
cin >> n;
cin.ignore(); // Pulisce il buffer
// Creazione del file in modalità scrittura
ofstream rubricaOut("rubrica.txt");
if (!rubricaOut) {
cerr << "Errore nell'apertura del file per la scrittura." << endl;
return 1;
}
Contatto contatto;
for (int i = 0; i < n; i++) {
cout << "\nInserisci il nome del contatto " << i + 1 << ": ";
getline(cin, contatto.nome);
cout << "Inserisci il numero di telefono: ";
getline(cin, contatto.telefono);
// Scrive il contatto nel file, separando i campi con una virgola
rubricaOut << contatto.nome << "," << contatto.telefono << endl;
}
rubricaOut.close();
// Lettura e visualizzazione dei contatti dal file
ifstream rubricaIn("rubrica.txt");
if (!rubricaIn) {
cerr << "Errore nell'apertura del file per la lettura." << endl;
return 1;
}
cout << "\n--- Rubrica dei Contatti ---" << endl;
string linea;
while (getline(rubricaIn, linea)) {
cout << linea << endl;
}
rubricaIn.close();
return 0;
}
💡 Caratteristiche dell'esercizio: • Struct Contatto: Organizza i dati in modo strutturato • cin.ignore(): Pulisce il buffer dopo
cin >>• Formato CSV: Campi separati da virgola per una facile elaborazione • Doppia operazione: Scrittura e successiva lettura dello stesso file
6. Esercizio Avanzato: Registro delle Presenze
🎯 Obiettivo: Implementa un programma che registri le presenze degli studenti, salvi i dati in un file, calcoli e visualizzi il totale delle presenze
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Presenza {
string nomeStudente;
bool presente; // true = presente, false = assente
};
int main() {
int n;
cout << "Quanti studenti vuoi registrare? ";
cin >> n;
cin.ignore();
ofstream registroOut("registro_presenze.txt");
if (!registroOut) {
cerr << "Errore nell'apertura del file per la scrittura." << endl;
return 1;
}
Presenza studente;
for (int i = 0; i < n; i++) {
cout << "\nInserisci il nome dello studente " << i + 1 << ": ";
getline(cin, studente.nomeStudente);
char risposta;
cout << "Lo studente è presente? (s/n): ";
cin >> risposta;
cin.ignore();
studente.presente = (risposta == 's' || risposta == 'S');
// Salva il record nel file
registroOut << studente.nomeStudente << "," << (studente.presente ? "Presente" : "Assente") << endl;
}
registroOut.close();
// Lettura del registro e calcolo del totale delle presenze
ifstream registroIn("registro_presenze.txt");
if (!registroIn) {
cerr << "Errore nell'apertura del file per la lettura." << endl;
return 1;
}
int totalePresenze = 0;
string record;
cout << "\n--- Registro Presenze ---" << endl;
while (getline(registroIn, record)) {
cout << record << endl;
// Se il record contiene "Presente", incrementa il contatore
if (record.find("Presente") != string::npos) {
totalePresenze++;
}
}
registroIn.close();
cout << "\nTotale presenze: " << totalePresenze << endl;
return 0;
}
💡 Caratteristiche dell'esercizio: • Input interattivo: L'utente inserisce dati dinamicamente • Conversione bool: Trasforma risposta s/n in valore booleano • Operatore ternario:
condizione ? vero : falsoper scegliere il testo • string::find(): Cerca sottostringhe per contare le presenze
7. Best Practices e Consigli
Regole fondamentali:
Controllo Errori
Verifica sempre se il file è stato aperto correttamente con if (!file)
Chiusura File
Chiudi sempre il file con close() per liberare risorse
Gestione Buffer
Usa cin.ignore() dopo cin >> per pulire il buffer
Modalità Appropriate
Scegli le flag giuste (ios::app, ios::trunc) per ogni operazione
Formato Dati
Usa separatori consistenti (virgole, punti e virgola) per file strutturati
Conclusioni
Punti chiave della gestione file:
ofstream
Per scrivere dati su file, creazione e modifica contenuti
ifstream
Per leggere dati da file, elaborazione e analisi
fstream
Per operazioni bidirezionali, lettura e scrittura combinate
Applicazioni Pratiche
Rubriche, registri, configurazioni, salvataggio dati applicazione
La gestione dei file con
<fstream>in C++ consente di interagire con dati esterni in modo semplice ed efficiente. Attraverso gli esempi sopra riportati è possibile gestire dati strutturati, applicare best practices per evitare errori e creare applicazioni che persistono i dati tra diverse esecuzioni. Buon coding! 🚀
Esercitazioni Pratiche C++
Metti in pratica ciò che hai imparato con queste esercitazioni complete
Tutte le Esercitazioni
12 esercitazioni complete per padroneggiare il C++