Salvare da file in una struct (c++)

Pubblicità

alley

Nuovo Utente
Messaggi
48
Reazioni
0
Punteggio
24
Ciao a tutti :ciaociao:
ho un problema nel salvare dati da file in una struct. Nel file è presente un elenco di libri in questo specifico formato(che non facilita la lettura) :
titolo autore data_di_ pubblicazione editore prezzo
(la data è scritta ad esempio in questa forma :10/12/2016)
Prima di tutto ho letto il numero di libri presenti nell'elenco(valutando il numero di caratteri '\n' e fin qui ci siamo).
ho creato una struct per contenere i vari dati di ogni libro e successivamente un array di struct (in base al numero di libri).
Adesso dovrei leggere i vari dati per ogni libro e salvarli nei relativi campi. Nel file ho pensato di separare i vari campi con una virgola in modo da facilitare la lettura.
Un ulteriore difficoltà è data dalla presenza nel file (per ogni libro) di caratteri di tipo diverso(interi e char) e dal '/' all'interno della data.
Come potrei leggere i vari dati salvandoli nei relativi campi?
grazie
 
Ultima modifica:
Prova una cosa del genere
Codice:
string str = "titolo,autore,data_di_ pubblicazione,editore,prezzo";
string word;
stringstream stream(str);
while( getline(stream, word, ',') )
   cout << word << "\n";

Un problema di questa soluzione e' che se la virgola e' nel titolo del libro non funziona
consiglio un delimitatore piu' sicuro tipo '§'
 
Prova una cosa del genere
Codice:
string str = "titolo,autore,data_di_ pubblicazione,editore,prezzo";
string word;
stringstream stream(str);
while( getline(stream, word, ',') )
   cout << word << "\n";

Un problema di questa soluzione e' che se la virgola e' nel titolo del libro non funziona
consiglio un delimitatore piu' sicuro tipo '§'
purtroppo non conosco la classe string(avrei dovuto specificarlo, scusami), di conseguenza non capisco il funzionamento di quel codice.
 
Ultima modifica:
per il C++ invoco @signore del tempo :inchino:
*compare* Wah, che esagerazione :asd:

@alley ti consiglio vivamente ti imparare la classe string, o almeno le operazioni basilari che però semplificano di molto il lavoro. Vedo che tratti argomenti già più avanzati di quanto necessiteresti per apprenderla; ti ci vorrebbero 5 minuti.

Se vuoi davvero sporcarti le mani, devi ricorrere a strumenti meno astratti e non per questo più semplici da utilizzare; anzi, il contrario. Il metodo più semplice penso sia leggere "stringhe" di lunghezza prefissata dal file poiché per leggerne a lunghezza variabile servirebbe un po' di codice in più, effettivamente andando a reinventare quanto std::string fa già. Scrivere quel codice richiederebbe molto più tempo che imparare la classe string!

Codice:
struct Libro {
   char titolo[32];
   char autore[32];
   char data[32];
   char editore[32];
   double prezzo;
};

Poi usi getline per leggere i primi campi, specificando ' ' come terminatore, ed infine >> per il prezzo. Poi controlli ad ogni iterazione che le letture abbiano avuto successo, altrimenti provvedi di conseguenza (EOF, formato errato ecc.).

Tipicamente l'I/O formattato in C++ è problematico, per questo è preferibile utilizzare librerie esterne. Reinventare la ruota, se non per scopi educazionali, difficilmente paga.
 
Ultima modifica:
*compare* Wah, che esagerazione :asd:

@alley ti consiglio vivamente ti imparare la classe string, o almeno le operazioni basilari che però semplificano di molto il lavoro. Vedo che tratti argomenti già più avanzati di quanto necessiteresti per apprenderla; ti ci vorrebbero 5 minuti.

Se vuoi davvero sporcarti le mani, devi ricorrere a strumenti meno astratti e non per questo più semplici da utilizzare; anzi, il contrario. Il metodo più semplice penso sia leggere "stringhe" di lunghezza prefissata dal file poiché per leggerne a lunghezza variabile servirebbe un po' di codice in più, effettivamente andando a reinventare quanto std::string fa già. Scrivere quel codice richiederebbe molto più tempo che imparare la classe string!

Codice:
struct Libro {
   char titolo[32];
   char autore[32];
   char data[32];
   char editore[32];
   double prezzo;
};

Poi usi getline per leggere i primi campi, specificando ' ' come terminatore, ed infine >> per il prezzo. Poi controlli ad ogni iterazione che le letture abbiano avuto successo, altrimenti provvedi di conseguenza (EOF, formato errato ecc.).

Tipicamente l'I/O formattato in C++ è problematico, per questo è preferibile utilizzare librerie esterne. Reinventare la ruota, se non per scopi educazionali, difficilmente paga.
La classe string non l'ho imparata perchè non rientrando nel programma, non la posso utilizzare, non per altro.
Per quanto riguarda la soluzione da te proposta, puoi essere più dettagliato? (aggiungo che per l'autore è specificato sia il nome che il cognome)
grazie
 
Ultima modifica:
Qualcosa non ti è chiaro nello specifico oppure sono io ad aver scritto una farragine?
non mi è chiaro il metodo da seguire, anche perché la parte complicata credo sia proprio l'implementazione (visto quel formato in cui sono riportati i dati nel file).
Quindi se possibilmente potresti indicare nello specifico i punti da seguire mi faresti un gran favore. (ci sto provando da un bel po', ma fin'ora senza risultato).
comunque, con il terminatore di getline che hai riportato, non si tiene conto che ad esempio per l'autore è specificato sia il nome che il cognome.

- - - Updated - - -

*compare* Wah, che esagerazione :asd:

@alley ti consiglio vivamente ti imparare la classe string, o almeno le operazioni basilari che però semplificano di molto il lavoro. Vedo che tratti argomenti già più avanzati di quanto necessiteresti per apprenderla; ti ci vorrebbero 5 minuti.

Se vuoi davvero sporcarti le mani, devi ricorrere a strumenti meno astratti e non per questo più semplici da utilizzare; anzi, il contrario. Il metodo più semplice penso sia leggere "stringhe" di lunghezza prefissata dal file poiché per leggerne a lunghezza variabile servirebbe un po' di codice in più, effettivamente andando a reinventare quanto std::string fa già. Scrivere quel codice richiederebbe molto più tempo che imparare la classe string!

Codice:
struct Libro {
   char titolo[32];
   char autore[32];
   char data[32];
   char editore[32];
   double prezzo;
};

Poi usi getline per leggere i primi campi, specificando ' ' come terminatore, ed infine >> per il prezzo. Poi controlli ad ogni iterazione che le letture abbiano avuto successo, altrimenti provvedi di conseguenza (EOF, formato errato ecc.).

Tipicamente l'I/O formattato in C++ è problematico, per questo è preferibile utilizzare librerie esterne. Reinventare la ruota, se non per scopi educazionali, difficilmente paga.
ho riletto le tue indicazioni e sono arrivato a questo:
ho definito un array di struct (avendo definito il tipo libro come hai specificato)
struct libro elenco[20];
poi (avendo definito lo stream openfile)
openfile.seekg(0,openfile.beg) in modo da riportare l'indicatore all'inizio del file in lettura (inizialmente ho letto il numero di libri presenti nel file e quindi l'indicatore era alla fine)

Codice:
while(!openfile.eof())
{
  for(i=0;i<20;i++)
  {openfile.getline(elenco[i].titolo,31,',');
  openfile.getline(elenco[i].autore,31,',');
  openfile.getline(elenco[i].data,31,',');
  openfile.getline(elenco[i].editore,31,',');
  openfile>>prezzo;
  openfile.seekg(1,openfile.cur);    //in modo da saltare il carattere '\n'
  } 
}


il codice che ho scritto è corretto?
ho notato con il debugger che l'istruzione openfile.seekg(0,openfile.beg) è come se non mi riportasse all'inizio del file, infatti non mi fa proprio entrare all'interno del while (condizione false).
è questo il problema?
 
Ultima modifica:
Per saltare un carattere, usa semplicemente ifs.ignore.
Codice:
 openfile.seekg(1,openfile.cur);
non so come possa compilare, perché dovrebbe essere
Codice:
 ifstream::cur

Codice:
openfile>>prezzo;
Non dovrebbe essere elenco.prezzo?
 
Per saltare un carattere, usa semplicemente ifs.ignore.
Codice:
 openfile.seekg(1,openfile.cur);
non so come possa compilare, perché dovrebbe essere
Codice:
 ifstream::cur

Codice:
openfile>>prezzo;
Non dovrebbe essere elenco.prezzo?

sì è come hai detto, cioè openfile>>elenco.prezzo, riscrivendolo ho sbagliato.
Il fatto è che nel while non entra proprio, è sbagliata l'istruzione per spostare l'indicatore all'inizio?
 
Ultima modifica:
Provando a compilare quella seekg non mi vengono segnalati errori -- strano, non saprei perché.

Ti è stato detto che controllare per EOF prima di leggere da un file è sbagliato, anche se non penso la sorgente dei problemi in questo caso. Hai provato a controllare lo stato dello stream/se il file è stato aperto?
 
Provando a compilare quella seekg non mi vengono segnalati errori -- strano, non saprei perché.

Ti è stato detto che controllare per EOF prima di leggere da un file è sbagliato, anche se non penso la sorgente dei problemi in questo caso. Hai provato a controllare lo stato dello stream/se il file è stato aperto?
sì e non mi da nessun errore nell'apertura del file. Nello specifico quella seekg l'ho vista da cplusplus.
comunque quello che ho fatto prima della seekg è questo
Codice:
while(!openfile.eof())
{ c=openfile.get();
  if(c=='\n')
  r++;     //num di libri, è un int
}
con la seekg successiva però è come se non ritornassi all'inzio del file
 
Ti dispiace postare tutto il codice? Possibilmente su siti come questo o questo, specialmente se prolisso.
ho risolto evitando il while iniziale (per leggere il numero di libri) e quindi anche la seekg, facendo così:
Codice:
while(!openfile.eof())
{
   [COLOR=#333333]openfile.getline(elenco[i].titolo,31,',');
   openfile.getline(elenco[i].autore,31,',');
   openfile.getline(elenco[i].data,31,',');
   openfile.getline(elenco[i].editore,31,',');
   openfile>>elenco[i].prezzo;
   i++;
   }
[/COLOR]

mi sembra essere la soluzione migliore, non credi?
 
Ultima modifica:
Pubblicità
Pubblicità
Indietro
Top