PDA

View Full Version : [C++]Classi e struct da file


TheBestNapoli
24-03-2011, 14:36
Ciao a tutti, sono ancora io XD, ho cominciato un altro esercizio, ma non riesco a procedere nello svolgimento. L'esercizio è il seguente:
Un veterinario deve organizzare, per il suo ambulatorio, l’agenda giornaliera delle visite. Per semplicità si supponga che i clienti di tale ambulatorio siano solo cani e gatti. Si progetti la classe animale e da essa si derivino le classi cane e gatto. La segretaria del veterinario riceve le prenotazioni telefonicamente ed immette da tastiera, su file sequenziale, in apposito record: il nome dell’animale, il tipo, la razza, l’età, la data della visita, il sesso ed il motivo della visita. Alla fine della giornata la segretaria stampa la lista delle prenotazioni ricevute in ordine crescente secondo la data.
Il problema è che io ho sempre avuto a che fare con classi semplici, i cui dati membro erano tipi semplici. Ad esempio creavo la classe Animale e da essa derivavo le classi Cane e Gatto, poi con i costruttori di default e le funzioni set e get creavo istanze delle classi e le stampavo. Ora non riesco a capire come leggere da un file una struct e implementarla con una classe. La funzione leggiDaFile è esterna alla classe? Sono nel panico, qualcuno potrebbe aiutarmi a capire come procedere? Grazie mille.

TheBestNapoli
24-03-2011, 16:26
Allora ho fatto la lettura da file dichiarando prima nell'header la struct
typedef char stringa[N];
typedef struct{
stringa data;
stringa nome;
stringa tipo;
stringa razza;
char sesso;
int eta;
stringa motivo;
}Animale;
typedef Animale Ambulatorio[N];

dopodichè ho implementato le funzioni leggiDaFile e stampa così
void leggiDaFile(Ambulatorio a, int &r)
{
r=0;
ifstream f;
f.open("ambulatorio.txt", ios::in);
if(!f)
{
cerr<<"ERRORE\n";
}
else
{
while(!f.eof())
{
f>>a[r].data;
f>>a[r].nome;
f>>a[r].tipo;
f>>a[r].razza;
f>>a[r].sesso;
f>>a[r].eta;
f>>a[r].motivo;
r++;
}
}
f.close();
}

void stampa(Ambulatorio a, int r)
{
cout<<"GIORNO\tNOME\tTIPO\tRAZZA\tSESSO\tETA’\tMOTIVO\n";
for(int i=0;i<r;i++)
cout<<a[i].data<<" "<<a[i].nome<<" "<<a[i].tipo<<" "<<a[i].razza<<" "<<a[i].sesso<<" "<<a[i].eta<<" "<<a[i].motivo<<endl;
}
e fin qui funziona ma non ho capito come entrano in gioco le classi... le ho create ma come le collego al discorso dello struct e della lettura da file? Scusate è da poco che studio le classi e vorrei capire bene come usarle. Grazie ancora per l'aiuto. :D

TheBestNapoli
31-03-2011, 12:57
Scusate per il ritardo ma ho avuto problemi di connessione :(
Cmq in questo periodo ho capito qualcosa in più e ho scritto il programma in modo che con le classi, tramite le funzioni membro, scrivo da tastiera i dati e il programma me li scrive su un file, dopodichè tramite la struct leggo da file i dati e li stampo a video.
Evito di postare tutto il codice poichè è enorme, ma mi rimane ancora una cosa da fare, che sembra la più semplice ma non mi funziona: si tratta di ordinare la stampa secondo il giorno. Allora ad esempio la funzione stampa() della classe Cane l'ho implementata così:
(Ambulatorio è il nome dell'array di record)
void Cane::stampa(Ambulatorio v, int &r)
{
r=0;
ifstream f;
f.open("ambulatorio.txt", ios::in);
if(!f)
{
cerr<<"ERRORE\n";
}
else
{
while(!f.eof())
{
f>>v[r].nome;
f>>v[r].sesso;
f>>v[r].eta;
f>>v[r].motivo;
f>>v[r].data;
f>>v[r].tipo;
f>>v[r].razza;
r++;
}
}
for(int i=0;i<r;i++)
{
for(int j=r-1;j>=i+1;j--)
if(strcmp(v[j-1].data,v[j].data) == 1)
{
stringa temp;
strcpy(temp,v[j].data);
strcpy(v[j].data,v[j-1].data);
strcpy(v[j-1].data,temp);
}
}
cout<<"\nGIORNO NOME TIPO RAZZA SESSO ETA’ MOTIVO\n";
for(int i=0;i<r;i++)
{
cout<<v[i].data<<" "<<v[i].nome<<" "<<v[i].tipo<<" "<<v[i].razza<<" "<<v[i].sesso<<" "<<v[i].eta<<" "<<v[i].motivo<<endl;
}
f.close();
}
togliendo quel pezzo di codice che dovrebbe fare l'ordinamento, l'output è
GIORNO NOME TIPO RAZZA SESSO ETA’ MOTIVO
18/06/2002 Romina Cane Cocker F 3 Gravidanza
17/06/2002 Nefert Gatto Europeo F 3 Vaccinazione
invece se metto quel pezzo di codice
GIORNO NOME TIPO RAZZA SESSO ETA’ MOTIVO
Romina Cane Cocker F 3 Gravidanza
17/06/2002 Nefert Cane Europeo F 5 Vaccinazione
18/06/2002
cioè in un certo senso me li ordina ma mi stravolge la stampa.
Come posso fare? Grazie mille a colo che mi aiuteranno. :D :D

pisto
31-03-2011, 13:24
if(strcmp(v[j-1].data,v[j].data) == 1)
mettici il >. strcmp ti da un valore maggiore o minore di zero se le due stringhe non sono uguali, non esattamente 1 o -1. Magari alcune implementazioni ti danno solo quei due valori, ma non credo proprio, e poi comunque lo standard è l'altro.
{
stringa temp;
strcpy(temp,v[j].data);
strcpy(v[j].data,v[j-1].data);
strcpy(v[j-1].data,temp);
}

qui stai spostando solo la data, non l'intero oggetto cane/gatto

EDIT:
mi sembra di capire che è un esercizio per la scuola. Se ti è permesso, perché non usi già la classe string e le funzioni di ordinamento che della libreria standard C++?

TheBestNapoli
31-03-2011, 14:35
Grazie per aver risposto :)
Allora ho capito il fatto della sostituzione di > al posto di == infatti sono andato a rivedere lo standard.
Credo di aver capito anche l'errore nell'algoritmo; allora se ho dichiarato nell'header:
typedef char stringa[N];
typedef struct{
stringa nome;
char sesso;
int eta;
stringa motivo;
stringa data;
stringa tipo;
stringa razza;
}record;
typedef record Ambulatorio[N];
allora l'algoritmo dovrebbe essere:
for(int i=0;i<r;i++)
{
for(int j=r-1;j>=i+1;j--)
if(strcmp(v[j-1].data,v[j].data) > 1)
{
record temp;
strcpy(temp.data,v[j].data);
strcpy(v[j].data,v[j-1].data);
strcpy(v[j-1].data,temp.data);
}
}
va bene così? Purtroppo però non funziona ancora. Help :confused: :D
PS. per quanto riguarda la libreria standard credo di aver fatto qualche accenno ma non so come usarla. Ho visto che c'è la funzione compare() ma non so degli algoritmi di ordinamento. Mi illuminersti? Grazie :D

pisto
31-03-2011, 14:57
io tutti i miei oggetti del tipo record li metterei in una list (http://www.cplusplus.com/reference/stl/list/) su cui poi chiamerei sort() passandogli un comparatore (http://www.cplusplus.com/reference/stl/list/sort/).

Riguardo alla tua seconda modifica, devi scambiare l'intero oggetto, quello che stai facendo è scambiare la data a due record lasciando tutto il resto della struttura al suo posto!

Secondo me, da te vogliono che tu faccia due classi, una cane e una gatto, ambedue derivate da animale. per come te l'hanno posta sembra inutile, perché non ti dicono alcun attributo specifico di "cane" o "gatto", ma attento ai prof rompiballe...

TheBestNapoli
31-03-2011, 15:36
Ok, diciamo che per il momento lascio da parte la libreria standard delle stringhe per mancanza di tempo, ma sicuramente la riprenderò in futuro.
Riguardo all'algoritmo che ho scritto non riesco a capire il problema... in realtà anche a me sono sembrati inutili tutti questi passaggi ma suppongo siano a scopo didattico; allora io ho usato le classi (base e derivate) per scrivere in input i dati, successivamente scrivo questi dati su un file. A questo punto tramite un array di record leggo da file tutti i dati ponendoli nei rispettivi campi. Quindi ora ogni animale è un record formato da diversi campi (tipo, nome, sesso, eta, ecc.); non riesco a capire come usare le classi ora... una volta fatto il controllo sulla data, dichiaro una variabile temp di tipo record (il nome della struct) e poi faccio gli scambi... di sicuro l'errore sarà in questi scambi ma non riesco a capire qual è. Grazie per l'aiuto che mi stai offrendo :D :D

pisto
31-03-2011, 18:45
for(int i=0;i<r;i++)
{
for(int j=r-1;j>=i+1;j--)
if(strcmp(v[j-1].data,v[j].data) > 1)
{
record temp=v[j];
v[j]=v[j-1];
v[j-1]=temp;
}
}
secondo me questo è giusto, perché sposta l'intero oggetto record. tu prima stavi spostando solo la data. se poi non funziona ancora passami il codice intero.

quello che penso che ti rimprovereranno è riguardo a questa direttiva che ti hanno dato:
Si progetti la classe animale e da essa si derivino le classi cane e gatto.
qui tu non l'hai fatto, hai fatto un struct record, il che anche a mio parere è sufficiente, ma stando a quello che ti hanno detto non è quello che vogliono.
Probabilmente loro vogliono una classe Animale, che ha come fields nome, sesso, eta, motivo, data; il costruttore dovrebbe prendere questi argomenti. Poi vorranno che crei due classi derivate, una Gatto e una Cane: quindi il tipo di animale è implicito. Non ti hanno deto di mettere altri fields che caratterizzino meglio Gatto e Cane, quindi sono due classi un po' inutili, ma vabeh.
Quindi, la tua lista invece che di oggetti tipo record sarà di oggetti tipo Animale. È opportuno che definisci un metodo tipo getType() (virtuale, implementato nelle classi Gatto e Cane) nella tua classe Animale che ti restituisca il tipo del tuo animale (sotto forma di stringa, tipo "gatto" o "cane"), e magari anche un metodo simile che ti dia la razza.

Tutto questo è fondamentalmente inutile, ma forse è questo che vogliono, se la mia interpretazione della tua frase è giusta:stordita:, sono anche poco abituato a problemi del genere perché la programmazione io l'ho imparata da autodidatta, e non ho mai dovuto risolvere questo tipo di esercizi