Esercizi sul file (superiori)
I seguenti esercizi riguardano File studiati nella Lezione 20 della Parte Prima. Essi sono divisi per paragrafi in modo tale da favorire la scelta degli esercizi specifici.
Es Files
[modifica]Esercizi sui files di testo e binari
[modifica]Esercizio n.1 Scrivi un programma che in modo sequenziale scriva su un file di testo nella prima riga la parola ciao, nella seconda il numero 34, nella terza il numero 34.12 e poi dopo averlo chiuso lo riapra per una lettura sequenziale delle informazioni contenute.
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{ // lavoro su file di testo ASCII - UNICODE
ofstream fo;// fo identificatore del file
fo.open("documenticarlo.txt");
fo<<"ciao"<<endl;
fo<<34<<endl;
float z=34.12;
fo<<z<<" "<<z<<endl;
fo.close();// rilascio risorse gestione del file
ifstream fi;
fi.open("documenticarlo.txt");
string a;
int b;
float c,d;
fi>>a;
fi>>b;
fi>>c>>d;
fi.close();
cout<<"la stringa e' "<< a<<endl;
cout<<"il numero intero e' "<< b<<endl;
cout<<"il numero float e' "<< c<<endl;
cout<<"il numero float e' "<< d<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Esercizio n.2 Nobile Chimico Il nobile chimico (chimico)
Il problema Il nobile chimico Alfredo produce nel suo laboratorio due sostanze liquide potenzialmente inquinanti: l’Aminozalina e il Brinofulo. A fine giornata le deve smaltire in appositi contenitori, dislocati lungo il tragitto che parte dal laboratorio e arriva alla sua abitazione. Per limitare le possibilità d’inquinamento, Alfredo deve distribuire l’Aminozalina nel maggior numero possibile di contenitori mentre deve dividere il Brinofulo nel minor numero possibile di contenitori. Tuttavia Aminozalina e Brinofulo non possono essere assolutamente mescolati nel medesimo contenitore, altrimenti la loro miscela esplode. Ogni volta che raggiunge un contenitore per lo smaltimento dei liquidi, Alfredo deve eseguire una sola delle tre seguenti azioni:
- (i) versare Aminozalina fino al riempimento del contenitore;
- (ii) versare Brinofulo fino al riempimento del contenitore;
- (iii) non versare nulla nel contenitore.
Data la quantità A di litri di Aminozalina e la quantità B di litri di Brinofulo da smaltire, e conoscendo l’elenco degli N contenitori (con rispettiva capacità) nell’ordine secondo cui sono incontrati lungo il tragitto dal laboratorio alla sua abitazione, Alfredo deve decidere se e quale sostanza versare in ciascun contenitore.
Dati di input
Il file input.txt contiene nella prima riga gli interi A e B (rispettivamente i litri di Aminozalina e di Brinofulo da smaltire) e il numero N di contenitori disponibili. Tali valori sono separati da uno spazio. Nelle successive N righe (usando una riga per ogni contenitore) è contenuto un numero per riga: tali numeri rappresentano le capacità dei singoli contenitori elencati nell’ordine in cui vengono incontrati da Alfredo.
Dati di output
Il file output.txt deve contenere N righe, una per ogni contenitore. Ogni riga contiene due numeri separati da uno spazio, rispettivamente il numero di litri di Aminozalina e di Brinofulo smaltiti nel corrispondente contenitore. Si noti che ogni riga deve contenere uno zero nei casi (i) e (ii) descritti sopra, e due zeri nel caso (iii).
Assunzioni
- • 1 < A, B < 10000
- • 1 < N < 100
- • Le singole capacità dei contenitori sono degli interi positivi di valore inferiore a 10000.
- • Le capacità dei contenitori sono sicuramente sufficienti per smaltire tutta l’Aminozalina e il Brinofulo prodotti.
- • I dati in input garantiscono l’esistenza di una (e una sola) soluzione ottima, quindi Alfredo ha un unico modo ottimo per smaltire le sostanze.
- • La soluzione ottima prevede che tutti i contenitori utilizzati vengano riempiti completamente (non può succedere che l’Aminozalina o il Brinofulo terminino prima che i contenitori effettivamente usati per lo smaltimento siano tutti completamente riempiti).
Esempi di input/output
File input.txt | File output.txt |
---|---|
20 25 7 | 1 0 |
1 | 0 13 |
13 | 4 0 |
4 | 5 0 |
5 | 8 0 |
8 | 2 0 |
2 | 0 12 |
12 |
using namespace std;
struct bidone
{ int pos;
int cap;//capacità
int a;
int b;
};
int main(int argc, char *argv[])
{ int qa,qb,n;
ifstream fi;
fi.open("input.txt");
fi>>qa;
fi>>qb;
fi>>n;
int i,j;
bidone elenco[n];
for(i=0;i<n;i++)
{ fi>>elenco[i].cap;
elenco[i].pos=i;
elenco[i].a=0;
elenco[i].b=0;
}
fi.close();
bidone temp;
for(i=1;i<n;i++)
for(j=n-1;j>=i;j--)
if(elenco[j].cap<elenco[j-1].cap)
{ temp=elenco[j];
elenco[j]=elenco[j-1];
elenco[j-1]=temp;
}
i=0;
while( qa>0)
{ elenco[i].a=elenco[i].cap;
qa=qa-elenco[i].cap;
i++;
}
i=n-1;
while( qb>0)
{ elenco[i].b=elenco[i].cap;
qb=qb-elenco[i].cap;
i--;
}
for(i=1;i<n;i++)
for(j=n-1;j>=i;j--)
if(elenco[j].pos<elenco[j-1].pos)
{ temp=elenco[j];
elenco[j]=elenco[j-1];
elenco[j-1]=temp;
}
ofstream fo;
fo.open("output.txt");
for(i=0;i<n;i++)
fo<<elenco[i].a<<" "<<elenco[i].b<<endl;
fo.close();
system("PAUSE");
return EXIT_SUCCESS;
}
esercizio n.3 Crea un file binario che registri 5 records contenenti ciascuno il nome di una città e la temperatura registrata, dopo aver chiuso il file riaprirlo e visualizzarne il contenuto
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
struct citta
{
char nome[20];
int temperatura;
};
int main(int argc, char *argv[])
{
citta elenco[5];
int i;
for(i=0;i<5;i++)
{
cout<<"nome citta'? ";
cin>>elenco[i].nome;
cout<<"temperatura? ";
cin>>elenco[i].temperatura;
}
ofstream fo;
fo.open("temperature.dat", ios::binary);
//for(i=0;i<5;i++)
//fo.write((const char*) &elenco[i],sizeof(citta));
fo.write((const char*) elenco,5*sizeof(citta));//sizeof elenco;
fo.close();
ifstream fi;
fi.open("temperature.dat", ios::binary);
citta elenco2[5];
fi.read((char*) elenco2,sizeof elenco2);
fi.close();
for(i=0;i<5;i++)
cout<<elenco2[i].nome<<" "<<elenco2[i].temperatura<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Esercizio n. 4 ci sono diverse merci ciascuna con :nome della merce,prezzo e quantità; crea un file di records e registra le informazioni di 3 merci differenti ( per salvare i records puoi o salvare i singoli records uno alla volta oppure salvare tutto l'array), chiudi il file e prova a leggere tutti i dati, chiudi il file e riaprilo posizionati per leggere solo il 2 record, poi aggiungi un nuovo record in coda e poi rileggi tutti i records
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
struct inventory
{ char item[20];
int quantita;
double costo;
};
int main(int argc, char *argv[])
{
inventory inv[3];
strcpy(inv[0].item,"A ciao");
inv[0].quantita=3;
inv[0].costo=10;
strcpy(inv[1].item,"B ciao");
inv[1].quantita=4;
inv[1].costo=11;
strcpy(inv[2].item,"C ciao");
inv[2].quantita=5;
inv[2].costo=12;
ofstream fout("inventario.dat",ios::binary);
if(!fout){cout<<"err apertura file";
return 1;
}
for(int i=0;i<3;i++)
fout.write((const char *) &inv[i], sizeof(inventory));
// fout.write((const char *) inv, 3*sizeof(inventory));
fout.close();
ifstream fin("inventario.dat",ios::binary);
if(!fin){cout<<"err apertura file";
return 2;
}
inventory elenco[3];
for(int i=0;i<3;i++)
fin.read((char *) &elenco[i], sizeof(inventory));
fin.close();
cout<<" i records letti sono"<<endl;
for(int i=0;i<3;i++)
{cout<<elenco[i].item<<endl;
cout<<"quantita'="<<elenco[i].quantita<<endl;
cout<<"prezzo'="<<elenco[i].costo<<endl<<endl;
}
cout<<"accesso in modalita' random"<<endl;
inventory z;
fstream fi2;
fi2.open("inventario.dat",ios::binary|ios::in|ios::out);
//leggo record 2 (numerazione da 0)
fi2.seekg( 2*sizeof(inventory),ios::beg);
fi2.read((char *) &z, sizeof(inventory));
cout<<"record n.2"<<endl;
cout<<z.item<<endl;
cout<<"quantita'="<<z.quantita<<endl;
cout<<"prezzo'="<<z.costo<<endl<<endl;
//voglio aggiungere un record
strcpy(z.item," D ciao");
fi2.seekp(0 ,ios::end);
fi2.write((const char *) &z,sizeof(inventory));
//controllo la struttura del file
cout<<"leggo tutti i records"<<endl;
fi2.seekg( 0, ios::beg);
while(fi2.read((char *)&z,sizeof(inventory)) != NULL)
{cout<<z.item<<endl;
cout<<"quantita'="<<z.quantita<<endl;
cout<<"prezzo'="<<z.costo<<endl<<endl;
}
fi2.close();
system("PAUSE");
return EXIT_SUCCESS;
}
esercizio n.5
Esistono 2 file di records uno clienti.dat con struttura del record (nome,codicecliente, importototaleacquisti) e uno fatture.dat con struttura record (nfattura, codice cliente, tipo vino, importo fattura) si vuole aggiornare l'importototale acquisti dei clienti (quindi il file clieni.dat) con le spese che risultano da ciascuna fattura di acquisto, il codice del cliente corrisponde al numero del record dove sono stati registrati i suoi dati
- /
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
struct cliente
{ char nome[20];
int codice;// corrisponde con n. record
float totale;
};
struct fattura
{ int nfattura;
int codice;// codice cliente a cui si riferisce la fattura
char vino[10];
float costo;
};
int main(int argc, char *argv[])
{
ifstream ffatture("fatture.dat", ios::binary);
fstream fclienti("clienti.dat", ios::binary|ios::in|ios::out);
int i,j;
fattura x;
cliente y;
for(i=0;i<40;i++)
{ffatture.read((char *) &x,sizeof x);
fclienti.seekg(x.codice*sizeof(fattura),ios::beg);
fclienti.read((char *) &y,sizeof y);
y.totale=y.totale+x.costo;
fclienti.seekp(x.codice*sizeof(fattura),ios::beg);
fclienti.write((const char *) &y,sizeof y);
}
ffatture.close();
fclienti.close();
system("PAUSE");
return EXIT_SUCCESS;
}
Esercizio n.6
Creare un file di records, i dati registrati su ciascun record sono: idpersona, nome, età e numeroditelefono. Tramite un menù di scelta premendo 1 si inserisce un nuovo record, premendo 2 si visualizza un particolare record (specificando l'idpersona) e premendo 3 si può modificare il numero del telefono di una certa persona (identificata dal suo id). l'idpersona rappresenta il numero del record stesso e così si può trovare facilmente la sua posizione in byte (idpersona*sizeof persona) , la numerazione parte da zero.
Di questo esercizio vengono date due soluzioni
- la prima "ferro" che usa una persona fittizia come record zero e che cancella tutti i dati inseriti ogni volta che il programma viene lanciato
- e una seconda soluzione "acciaio" che meno didatticamente risolve il problema della creazione del file se non esiste o lo apre senza cancellarne i dati se esiste
//ferro
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
struct persona{int id;
char nome[20];
int eta;
char nt[10];
};
int main(int argc, char *argv[])
{
persona a;
int i, x,risp;
fstream f;
f.open("elenco.dat", ios::binary|ios::out);
a.id=0;
strcpy(a.nome,"ferro");
a.eta=18;
strcpy(a.nt,"012345");
f.write((char*) &a, sizeof a);
f.close();
do{cout<<" 1 ins nuovo record, 2 vis record , 3 modificare numero telefono ";
cin>>x;
switch(x)
{case 1: f.open("elenco.dat",ios::binary|ios::out|ios::in);
f.seekg(-1*sizeof(persona), ios::end);
f.read((char*) &a, sizeof a);
a.id++;
cout<<"nome ";
cin>>a.nome;
cout<<"età ";
cin>>a.eta;
cout<<"numero di telefono ";
cin>>a.nt;
f.seekp(0, ios::end);
f.write((char*) &a, sizeof a);
f.close();
break;
case 2: cout<<"inserisci id della persona da ricercare ";
cin>>risp;
f.open("elenco.dat",ios::binary|ios::in);
f.seekg(risp*sizeof(persona), ios::beg);
f.read((char*) &a, sizeof a);
cout<<a.id<<" "<<a.nome<<" "<<a.eta<<" "<<a.nt<<endl;
f.close();
break;
case 3: cout<<"inserisci id della persona da modificare ";
cin>>risp;
f.open("elenco.dat",ios::binary|ios::in|ios::out);
f.seekg(risp*sizeof(persona), ios::beg);
f.read((char*) &a, sizeof a);
cout<<"dati attuali";
cout<<a.id<<" "<<a.nome<<" "<<a.eta<<" "<<a.nt<<endl;
cout<<"inserisci il nuovo numero di telefono ";
cin>>a.nt;
f.seekp(risp*sizeof(persona), ios::beg);
f.write((char*) &a, sizeof a);
f.close();
}
}
while(x!=0);
return 0;
}
//acciaio
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
struct persona{int id;
char nome[20];
int eta;
char nt[10];
};
int main(int argc, char *argv[])
{
persona a;
int i, x,risp;
int ultimo;
fstream f;
//creo il file se non esiste
f.open("elenco.dat", ios::binary|ios::in);
if(!f)
{ cout<<"file elenco.dat creato "<<endl;
f.open("elenco.dat", ios::binary|ios::out);
}
f.close();
// apro elenco.dat per operazioni di I/O
f.open("elenco.dat", ios::binary|ios::out|ios::in);
//determino il numero di records presenti nel file lunghezzafile/dimsingolorecord
f.seekg(0,ios::end);
ultimo=f.tellg()/sizeof(persona);
do{cout<<"Premi 1 inserire nuovo record"<<endl;
cout<<" 2 visualizzare record"<<endl;
cout<<" 3 modificare numero telefono "<<endl;
cout<<" 0 per uscire"<<endl;
cin>>x;
switch(x)
{case 1: a.id=ultimo;
cout<<"nome ? ";
cin>>a.nome;
cout<<"età ? ";
cin>>a.eta;
cout<<"numero di telefono ? ";
cin>>a.nt;
f.seekp(0, ios::end);
f.write((char*) &a, sizeof a);
f.flush();
ultimo++;
break;
case 2: cout<<"inserisci id della persona da ricercare ";
cin>>risp;
f.seekg(risp*sizeof(persona), ios::beg);
f.read((char*) &a, sizeof a);
cout<<a.id<<" "<<a.nome<<" "<<a.eta<<" "<<a.nt<<endl;
break;
case 3: cout<<"inserisci id della persona da modificare ";
cin>>risp;
f.seekg(risp*sizeof(persona), ios::beg);
f.read((char*) &a, sizeof a);
cout<<"dati attuali";
cout<<a.id<<" "<<a.nome<<" "<<a.eta<<" "<<a.nt<<endl;
cout<<"inserisci il nuovo numero di telefono ";
cin>>a.nt;
f.seekp(risp*sizeof(persona), ios::beg);
f.write((char*) &a, sizeof a);
}
}
while(x!=0);
f.close();
return 0;
}