Si consideri il file anagrafica.csv della fig. [1] seguente, ottenuto dall’esportazione nel formato CSV della tabella del foglio di lavoro di Excel della fig. [2]. Si tratta dello stesso file di esempio utilizzato in un altro articolo (link articolo), questa volta però vogliamo realizzare la cancellazione e la modifica di un record di cui si fornisce la posizione.
Si fa notare che il file anagrafica.csv è un file di testo che contiene record a lunghezza variabile: ogni sua riga è un record i cui campi sono separati con un carattere punto e virgola. Esso quindi ha un’organizzazione sequenziale, pertanto, sappiamo (link articolo) presenta forti limitazioni sulle operazioni che possono essere eseguite su di esso.
La cancellazione di un record
La cancellazione di un record del file non può essere eseguita operando direttamente e solo ed esclusivamente sul file. In generale, la cancellazione di un record all’interno di un archivio può realizzarsi o attraverso una più efficiente cancellazione logica, che consiste nel marcare il record da cancellare con la scrittura di un prefissato carattere (o di un’opportuna sequenza di caratteri) in un campo fissato del record; oppure attraverso una cancellazione fisica, che consiste nella riscrittura di tutti i record successivi a quello da cancellare, a partire dalla sua posizione. In questo caso nessuno dei due tipi di cancellazione è realizzabile, in quanto un record può essere scritto solo o a partire dall’inizio del file, con perdita di tutto il suo contenuto, o aggiungendolo in coda a quelli già esistenti.
L’unico modo di procedere può essere quello di riscrivere l’intero file in un file di appoggio, secondo lo schema della figura seguente, e alla fine cancellare il vecchio file e rinominare il file di appoggio con il nome del vecchio file.
Ciò può essere ottenuto in C++ con il seguente codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <iostream> #include <fstream> #include <string> #include <stdio.h> using namespace std; int main(){ string s; int p; //apre in LETTURA il file in cui cancellare il record ifstream miofile("anagrafica.csv"); //apre in RISCRITTURA il file di appoggio ofstream fAppoggio("appoggio.csv"); cout<<"Inserisci la posizione del record da cancellare: "; cin >> p; //legge i record sequenzialmente getline(miofile, s); //legge il primo record del file di partenza int c=1; //contatore per la posizione da raggiungere while(!miofile.eof()){ if(c!=p) //se la posizione in cui siamo è diversa da quella in cui cancellare fAppoggio<<s<<endl; //ricopia nel file di appoggio solo i record che non devono essere cancellati getline(miofile, s); //legge il record successivo del file di partenza c++; } miofile.close(); fAppoggio.close(); remove("anagrafica.csv"); //elimina il file vecchio rename("appoggio.csv", "anagrafica.csv"); //dà al file di appoggio il nome del file vecchio return 0; } |
La modifica di un record
Anche in questo caso, la possibilità di scrittura solo in coda (append) fa si che la modifica di un record del file possa avvenire solo riscrivendo l’intero file, utilizzando un file di appoggio secondo lo schema della figura seguente.
Ciò può essere ottenuto in C++ con il seguente codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include <iostream> #include <fstream> #include <string> #include <stdio.h> using namespace std; void stampaRiga(string); void modifica(string&); int main(){ string s; int p; //apre in LETTURA il file in cui modificare il record ifstream miofile("anagrafica.csv"); //apre in RISCRITTURA il file di appoggio ofstream fAppoggio("appoggio.csv"); cout<<"Inserisci la posizione del record da modicare: "; cin >> p; //legge i record sequenzialmente getline(miofile, s); //legge il primo record del file di partenza int c=1; //contatore per la posizione da raggiungere while(!miofile.eof()){ if(c=p) //se la posizione in cui siamo è quella in cui bisogna modificare modifica(s); fAppoggio<<s<<endl; //ricopia nel file di appoggio il record getline(miofile, s); //legge il record successivo del file di partenza c++; } miofile.close(); fAppoggio.close(); remove("anagrafica.csv"); //elimina il file vecchio rename("appoggio.csv", "anagrafica.csv"); //da' al file di appoggio il nome del file vecchio return 0; } void modifica(string& s){ string as; cout<<"RECORD DA MODIFICARE:"<<endl; stampaRiga(s); s=""; cout<<"Inserisci il cognome: "; cin.ignore(80, '\n'); getline(cin, as); s=s+as+';'; cout<<"Inserisci il nome: "; getline(cin, as); s=s+as+';'; cout<<"Inserisci l'indirizzo: "; getline(cin, as); s=s+as+';'; cout<<"Inserisci il cap: "; getline(cin, as); s=s+as+';'; cout<<"Inserisci la citta': "; getline(cin, as); s=s+as; } //Estrae da riga i campi in maniera sequenziale e li visualizza a video void stampaRiga(string riga){ riga=riga +";"; //aggiunge il carattere speciale di fine campo anche all'ultimo campo while(riga.length()!=0){ //visualizza il primo campo della riga cout<<riga.substr(0, riga.find(";", 0))<<endl; //cancella nella riga il campo appena visualizzato (compreso il ;) riga.erase(0, riga.find(";", 0)+1); } cout<<endl; } |