Newsgroup: it.comp.lang.c++
Titolo: Tornare ad inizio file

Sto realizzando una procedura che legge riga per riga un file utilizzando
getline
arrivato alla fine del file ho bisogno di riposizionarmi all'inizio dello
stesso possibilmente senza doverlo chiudere e riaprire.
Sto utilizzando la classe ifstream e visual c++ 5
Avete qualche idea?
Ciao
Terenzio

...

Supponendo che tu sia usando la libreria standard
(#include <fstream>, ecc, NON #include <fstream.h>
che e` li` solo per compatibilita` col passato):
Un ifstream incapsula un filebuf, e puoi ottenere un
puntatore al filebuf col metodo rdbuf di ifstream;
qualsiasi streambuf (da cui filebuf eredita) ha un metodo:
pos_type pubseekoff(off_type off, ios_base::seekdir way,
    ios_base::openmode which = ios_base::in | ios_base::out);
Quindi, se la tua variabile std::ifstream si chiama, ad
esempio, pippo, l'istruzione:
    pippo.rdbuf()->pubseekoff(0, std::ios_base::beg);
dovrebbe fare esattamente quel che desideri, cioe`,
ricominciare a leggerlo dall'inizio.
Alex

che e` li` solo per compatibilita` col passato):
No prurtroppo sto ancora utilizzando fstream.h, non ho avuto ancora modo di
studiare ed utilizzare le librerie standard (se non per qualche semplice
caso o provando qualcosa postato sulle news), questa gestione mi serve molto
urgentemente e sono andato + che sul sicuro sul veloce per le mie
conoscenze....
Cmq non appena avrò del tempo cercherò di convertire la procedura con codice
standard, quindi il tuo consiglio mi sarà molto utile in seguito, grazie.
Ne approfitto per chiedervi se esiste una documentazione decente delle
librerie standard in rete dato che la documentazione di visaul c++ in
proposito lascia a desiderare.
Ciao
Terenzio

 conoscenze....
Non sono per niente un esperto, ma sono riuscito a risolvere questo
problema
nel seguente modo:
fstream file;
file.open("input",ios::in);        // aprilo
while(!file.eof())
{
 ...leggi il file ...
}
file.clear(); 
file.seekg(0,ios::beg);            // questo ti riporta all'inizio
Sono sicuro che esistano modi molto migliori per fare la stessa cosa, ma
per il momento forse questo ti puo' risolvere il problema.
Fammi sapere se funziona.
Ciao,
Massimo
-- 
Massimo Boninsegni
Department of Physics 
San Diego State University
http://rainbow.sdsu.edu/~massimob

proposito lascia a desiderare.
Sul sito Microsoft c'e`, scaricabile gratuitamente o consultabile in
rete, un grazioso pacchetto di doc per quella che chiamano "STL
in VC++" -- non e` tutta la libreria standard, ma puo` servire.
Su 
www.dinkumware.com
 c'e` un reference manual in linea sulla
libreria standard (penso dello stesso tenore di quello fornito da
Microsoft, visto che Plauger, di Dinkumware, ha fornito anche la
libreria alla MS).  Plauger, Stepanov (l'originale autore di "STL"),
e una-due altre persone, hanno scritto un libro sulla libreria
standard C++, che uscira` da un giorno all'altro (
amazon.co.uk
lo da ancora come "not released by publisher", ma d'altronde
da` cosi` anche la nuova edizione del Petzold, e quella SO che
in USA e` gia` uscita...).
Alex

 }
In questo modo ti leggi due volte l'ultima riga.  Questo non e' Pascal:
l'EOF viene riconosciuto DOPO la lettura e non prima.
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

in VC++" -- non e` tutta la libreria standard, ma puo` servire.
Gragie, è veramente ottimo...
A volte nella documentazione di microsoft si finisce per perdersi,
sopratutto in visual c++ dove capita di trovare la cosa che ti serve in
visual basic visual j++ ecc.. e non per il linguaggio per cui lo cerchi.
Per argomenti già complessi come credo che sia lo standard c++ library avere
una documentazione chiara sia fondamentale...altrimenti ci si scoraggia
presto. ;)
Ciao
Terenzio

Maurizio Loreti wrote:

Mah... Prima di scrivere quanto ho scritto ho provato a realizzarlo, e ti
garantisco che funziona sulla mia macchina (linux g++) senza alcuna doppia
lettura dell'ultima riga. Tra l'altro non e' certo una procedura che mi sia
inventato io, la mettono sui libri per principianti... :-)
Saluti,


ancora dare conferma sull'effettiva qualita` del testo.
k, a proposito di libri quale di questi mi consigli di leggere per primo e
in che sequenza gli altri
Inside the c++ object model
Design patterns
Advanced c++
The c++ programming language
quali altri consigli o pensi che debbano essere letti prima...
Ciao
Terenzio



Ti consiglio di leggere la FAQ list di comp.lang.c .  Questo argomento
e' trattato in dettaglio assai maggiore di quanto potrei fare io.
In sintesi: l'indicatore di EOF viene settato nello stream DOPO che
l'EOF e' stato letto; se tu hai nel tuo buffer l'ultima riga del file
e fai una ulteriore lettura, viene rivelato l'EOF ed il contenuto del
buffer rimane immutato.


 buffer rimane immutato.
Le piccole gioie dei newsgroups... :-)
Allora, chiudiamo la discussione (in effetti non si puo' nemmeno definire tale)
cosi': io mi leggo le FAQ, tu magari prova a fare girare il seguente programma:
#include <fstream.h>
int main (void)
{
#define linelength 80
char string [linelength];
fstream file ;
file.open("prova",ios::in);
while(!file.eof())
{
  file >> string;
  cout << string << " " ;
 }
 cout << endl;
 file.clear();
 file.seekg(0,ios::beg);
 file >> string;
 cout << string << endl;
}
con  il seguente file di ingresso chiamato prova
riga1
riga2
riga3
riga4
L'output di questo programma e':
riga1 riga2 riga3 riga4
riga1
come richiesto nel messaggio originale. L'unica stringa che appaia due volte e'
riga1, il che va bene perche' lo scopo originale era, per l'appunto, dimostrare
come si possa tornare all'inizio del file.
Tutte le altre stringhe appaiono solo una volta.
Quante volte venga letta ogni riga non lo so, non mi interessa e non c'entra con
quanto si discuteva inizialmente; l'output, che e' l'unica cosa di cui si
discutesse, e' quello richiesto. Ho utilizzato il costrutto while perche' ho
assunto che il numero di righe nel file di ingresso sia ignoto.


presto. ;)
Secondo me l'argomento merita ampiamente l'acquisto di un libro;
credo (spero!, ma le recensioni che ne ho letto paiono confermarlo)
che "Generic Programming and the Stl : Using and Extending the C++
Standard Template Library" (Addison-Wesley Professional Computing
Series, autore: Matthew H. Austern) sia tanto buono quanto cio` che
ho letto in passato di questo autore lascia sperare, nonostante la
"gaucherie" di usare Stl nel titolo... (e` uno dei due testi che ha vinto
l'award della Association of C and C++ Users, 
www.accu.org
, come
miglior testo pubblicato nel 1998; l'altro e` l'ultimo di J. Coplien,
"Multi-Paradigm Design for C++", e, mirabile dictu, Austern ha avuto
l'oro e Coplien si e` dovuto accontentare dell'argento...).  Purtroppo
www.amazon.co.uk
 non me li ha ancora consegnati, per cui non posso
ancora dare conferma sull'effettiva qualita` del testo.
Alex

quali altri consigli o pensi che debbano essere letti prima...
Se non conosci gia` il C++, nessuno di questi ottimi libri e`
l'ideale per impararlo -- l'unico di questi che ha una chance di
funzionare come "primo libro" e` Stroustrup, "The C++
Programming Language" (3a edizione, *rigorosamente*: NON
leggere versioni precedenti, relative a dialetti del linguaggio
ormai vecchi di MOLTI anni, ti confonderebbero le idee piu`
che chiarirtele).  Per imparare, l'ideale e` Lippman e Lajoie,
"C++ Primer", 3a edizione, Addison-Wesley.
Una volta che il linguaggio lo conosci:
-- se ami "andare sul concreto", avere un modello di come
    il compilatore puo` trattare il tuo codice, Lippman, "Inside
    the C++ Object Model", tenta di darti questo modello;
-- se ami la progettazione, e le astrazioni, "Design Patterns"
    e` ideale da questo punto di vista
Dopo uno di questi due, lo Stroustrup di cui sopra, e poi l'altro
di questi due.
Il Coplien, "Advanced C++", va letto per ultimo, per due
ragioni: usa un dialetto non aggiornato, _E_, e` DAVVERO
"avanzato": gli "idiomi" che presenta, pur preziosi, richiedono
una buona padronanza del linguaggio, un buon modello di
cosa il compilatore fa corrispondere ai vari costrutti, E una
idea di come funziona la progettazione a oggetti -- giunge
dunque, idealmente, a coronamento degli altri.
In questa ottima bibliografia, a parte un "Primer" come il
Lippman e Lajoie, mancano solo i due grandiosi testi di
consigli pratici di Meyers: "Effective C++" (2a edizione,
mi raccomando) e "More Effective C++" (1a e unica
edizione); si possono leggere subito dopo un primer, o
in qualsiasi altro punto del percorso di studi -- o, meglio,
leggere e rileggere piu` di una volta, e soprattutto,
metterli in pratica...!-).
Esistono altri buoni e ottimi testi di C++, ma chi avesse
masticato _e digerito_ tutti quelli qui elencati ne avrebbe
gia` una padronanza *decisamente* superiore a quella
del 90% dei programmatori che lo usano...!-)
Alex

riga1
L'output con un compilatore standard (appena provato!) e` invece:
riga1 riga2 riga3 riga4 riga4
riga1
esattamente come lo standard del linguaggio prescrive.
Apparentemente, il tuo compilatore ha un qualche bug, che ti
maschera il bug del tuo programma.
Alex

 Alex


sembra strano, pensavo che fosse uno dei piu' diffusi.
Non seguo bene la tua logica.  Si`, g++ e` uno dei compilatori piu`
diffusi; lo e` anche Microsoft Visual C++; pensi dunque che, a causa
di questa ampia diffusione, Microsoft Visual C++ non abbia bachi che
lo fanno discostare dallo standard?!  Sulla stessa logica, dovresti
allora pensare anche che Windows95 e` "piu` standard" e meno
bacato di Windows/NT, visto che e` assai piu` diffuso...?
Questo scambio, mi pare, mostra chiaramente il pericolo dell'approccio,
assai popolare, per cui, invece di leggersi e studiarsi lo standard, alcuni
programmatori procedono "empiricamente", alla "vediamo un po' che
succede cosi`" -- magari con versioni obsolete di compilatori e librerie
(come sarebbe chi, per il g++, usasse 2.8.x o addirittura -- non ridere,
ce ne sono! -- 2.7.x, o, per VC++, 5.0 o -- di nuovo, non ridere, ti giuro
che ce ne sono! -- 4.x...!).  In questo modo, invece del linguaggio, si
impara un qualche dialetto definito dall'insieme dei bug della specifica
versione utilizzata per gli esperimenti.  Il peggio e` quando, sulla base
di questo empirismo, si "correggono" giuste osservazioni sul linguaggio,
come facevi tu con quelle di Massimo Loreti...!
Dicevi, inoltre, che questa bella lezione (sbagliata) "la mettono sui libri
per principianti": ti prego di rivelarci gli specifici libri in questione,
cosi`
da potere salvare futuri principianti da erroracci del genere (chissa`
perche`, ma, non sarei stupito a scoprire che si tratta di libri di un
certo H.S...).
Alex

 sembra strano, pensavo che fosse uno dei piu' diffusi.
Il fatto che sia diffuso non vuol dire che segua lo standard, soprattutto se
si e' diffuso quando ancora non c'era lo standard.
In particolare, 
  g++ 2.7 (o precedente) e' molto lontano dallo standard
  g++ 2.8 e' un po' piu' vicino, ma ha vari problemi; meglio evitarlo
  egcs 1.0.x  abbastanza vicino allo standard, ma non supporta i namespace
  egcs 1.1  standard; qualche piccolo bug con i namespace, risolto dalla 
    versione 1.1.1 che dovrebbe uscire adesso.
Il problema pero' in questo caso e' la libreria di I/O, che e' vecchissima e 
completamente non standard. Gli stream sono di tipo vecchio senza template;
streambuf ha un'interfaccia non standard; non ci sono sstream, ma solo i
vecchi strstream; in piu' ci sono vari problemi anche nell'implementazione,
basata sui 'FILE' del C invece che sulle specifiche dello standard.
Naturalmente egcs 1.1, essendo standard, puo' compilare e supportare benissimo
una libreria standard, basta che qualcuno la scriva.
	Mauro

 riga1
La differenza di comportamento tra la diverse librerie sta nel fatto
che, quando viene rivelato l'EOF, l'operatore >> non lascia inalterato
il buffer 
ma lo sovrascrive comunque.
Cosa dice lo standard a proposito ?
P.S.
Come faccio a sapere quale versione di librerie sto usando ?
Su Linux (RedHat 5.1) uso la glib 1.0.1, che si comporta come sopra.
Lo stesso output ho ottenuto su Digital Unix  (OSF1 V4.0 878 alpha)
Su IBM AIX 3.4 invece il buffer resta inalterato (la riga4 viene 
stampata due volte)
Saluti
Fabio Lopiano

 Alex
Nessun problema: lunedi saro' lieto di svelare tale segreto :-)
In realta' i titoli me li ricordo, gli autori no.
Uno e' ``Teach yourself C++ in 21 days''  :-)  ma non mi pare che le iniziali
dell'autore siano H. S.
L'altro si intitola ``Practical C++ programming''. Non mi ricordo in quale dei
due ho trovato questo costrutto, ma sicuramente non me lo sono inventato io
(non conosco abbastanza C++ per potermi inventare nemmeno cose sbagliate :-)
Pero' faccio presente che ci sono anche degli appunti on-line che dicono la
stessa cosa: ad esempio,
a 
http://hs.linn.k12.mo.us/~stockd/c_class/c_notes/while_loops_mine.html
 il
costrutto che io sto utilizzando viene proposto.
Dovrebbe in teoria trattarsi di appunti di uno che insegna C++. Naturalmente
possono essere sbagliati, ma mi concederai che per un principiante puo' essere
difficile rendersene conto.


Come faccio a sapere quale versione di librerie sto usando ?
Non c'e`, purtroppo, un metodo generale, che io sappia.
Alex

difficile rendersene conto.
Non sono sbagliati per nulla, ma non dicono assolutamente quello
che tu dici che dicono...:-).  A questo punto, non sono, onestamente,
molto motivato a frugare grossi libri di testo per vedere se dicono
veramente delle cose sbagliate, oppure, come questa URL che hai
citato, delle cose giuste, e secondo me anche chiare, che pero` tu
scegli, misteriosamente, di prendere come "rafforzamento" delle
idee errate che sembri avere sulla semantica di eof e >>.
Quello che mi sembra chiaro, e` che Loreti ha fatto BENISSIMO a
segnalare l'errore nel tuo codice, visto che c'e` dietro, in effetti,
un malinteso sulla semantica dell'input in C++, apparentemente
"rafforzato" da un bug di una diffusa libreria di I/O (che ha una
semantica ancora diversa...), e forse diffuso.  Se possiamo in
qualche modo chiarirlo, penso che non possa che essere un
beneficio per tutti.  Similmente, tu hai fatto benissimo a non tacere,
se i dubbi non ti si erano ancora affatto dissipati, anche se qualche
lettore puo` aver preso una tua espressione, che voleva essere di
dubbio, per una che pareva invece di certezza (errata) -- i malintesi
passano, ma solo se, parlandone, ce li si chiarisce.
Alex