View Full Version : poblema con "iso::beg"
Carmine01
02-03-2014, 12:50
salve, spero possiate aiutarmi:
Ho scritto un codice che confronta, ad una ad una, ogni riga di file con tutte le righe di un altro file. Scrive la riga che non è stata trovata su un altro file.
Il problema è che FINITO il secondo file vorrei che il suo puntatore cominciasse dall'inizio per un nuovo confronto.
Per fare ciò ho messo a loop l'apertura e chiusura del file (cosa che dovrebbe risolvere il problema) ma non funziona. Allora sono passato ad iso::beg che dovrebbe portarmi il puntatore il cima al file--> NON FUNZIONA.
Quindi mi ritrovo che fa il confronto solo della prima riga di un file. Una volta arrivato alla file, il secondo file, MUORE non è più possibile usarlo e quindi tutti i successivi risultati "risultano NON PRESENTI" e quindi scritti nel file di output o.o
**********************AGGIORNAMENTO*****************************
Non so cosa ho cambiato nel vecchio codice, in realtà NIENTE, ma adesso "funziona meglio":
facendo altri esperimenti ho capito che il problema del non funzionamento di "ios::beg" inizia a sussistere quando il secondo file arriva per la prima volta alla fine. Da allora non è più in grado di tornare all'inizio!!
P.S. ho lasciato i codici di commenti per dare un idea più chiara nel caso lo compiliate
int main(){
ifstream in1, in2;
ofstream ou;
char fr[1000], temp[1000];
bool idem=false;
in1.open("1.txt");
ou.open("risultati_assenti.txt");
in2.open("2.txt");
while(!in1.eof()) {
in1>>fr;
cout<<"\nPRENDO fr: "<<fr;
// in2.open("2.txt");
in2.seekg(0, ios::beg);
idem=false;
if (!in2.eof()) cout<<"\nENTRA";
while(!in2.eof()) {
in2>>temp;
cout<<"\nPRENDO temp: "<<temp;
if (!strcmp(fr, temp)) {
idem=true;
cout<<"\nVERO";
break;
}
}
if (idem==false) {ou<<fr<<endl; cout<<"\nSCRITTO: "<<fr;}
// in2.close();
}
ou.close();
in1.close();
in2.close();
cout<<endl;system("pause");
}
GRAZIE IN ANTICIPO
Daniels118
04-03-2014, 08:28
Per favore aggiusta l'indentazione...
Non ci posso credere, nel web non ho trovato un solo esempio pulito di come si legge un file, solo le cose più assurde...
Allora, o fai la lettura direttamente nella condizione del while, in modo che avvenga prima la lettura e poi viene verificato se è andata bene, oppure fai una lettura preventiva fuori ciclo come è stato fatto qui:
http://hwupgrade.it/forum/showpost.php?p=40793699&postcount=27
Una volta che avrai aggiustato questi elementi di base potremo verificare il resto.
Carmine01
05-03-2014, 00:47
Grazie della risposta, Daniels.
Questo è il codice attuale:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "D:\Programmi\Dev\Carminefunz.cpp"
using namespace std;
const int dimstring=1000;
int main(){
ifstream in1, in2, tmp;
ofstream ou;
char fr[dimstring], temp[dimstring];
bool idem=false;
int righi1=0, conta=0, righi2=0;
cout<<"\nRinomina il file di testo che possiede tutti gli elementi utili al confronto chiamandolo:\n\"1.txt\" oppure \"1\"\nA seconda se (rispettivamente) le estensioni sono visibili o meno.\n\nRinomica il secondo file in cui POTREBBERO essere mancaze rispetto al primo:\n\"2.txt\" oppure \"2\"";
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("2.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 2/2.txt MANCA.\n"; system("pause"); exit(1);}
while (!tmp.eof()) {righi2++; tmp>>fr;}
tmp.close();
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("1.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 1/1.txt MANCA.\n"; system("pause"); exit(1);}
while (!tmp.eof()) {righi1++; tmp>>fr;}
tmp.close();
in1.open("1.txt");
ou.open("risultati_assenti_in_2.txt");
in2.open("2.txt");
while(!in1.eof()) {
in1>>fr;
//cout<<"\nPRENDO fr: "<<fr;
// in2.open("2.txt");
in2.seekg(0, ios::beg);
idem=false;
conta=0;
//if (!in2.eof()) cout<<"\nENTRA";
//fa il confronto di tutti i righi tranne l'ultimo (gl'impedisco di "arrivare alla fine")
while(conta<righi2-1) {
conta++;
in2>>temp;
//cout<<"\nPRENDO temp: "<<temp;
if (!strcmp(fr, temp)) {
idem=true;
//cout<<"\nVERO";
break;
}
}
if (idem==false) {ou<<fr<<endl;/* cout<<"\nSCRITTO: "<<fr;*/}
// in2.close();
}
ou.close();
in1.close();
in2.close();
I problemi sono che:
1) "tmp.open("1.txt");" non apre il file, non lo trova, suppongo.
2) Una volta che un file viene aperto-usato-chiuso alla sua riapertura resta all'ultima posizione trovata. (Promblema, appunto, del vecchio codice).
3) (collegata alla 2) ) Quando x.eof(); da segnali positivi (perchè arrivato appunto alla fine), il file a in questione non lo si può più aprire e sperare che cominci dall'inizio, NOSSIGNORE, il puntatore resta nell'oblio più nascosto della fine del file.
Daniels118
05-03-2014, 14:58
Beh, se non crei i file necessari io posso farci poco :D
Comunque non hai ancora applicato un algoritmo corretto per la lettura del file.
Carmine01
05-03-2014, 16:19
Mi sermbrava inutile specificare che il file esiste.
Per quanto riguarda la corretta applicazione della lettura di file, potresti guidarmi tu con tuoi esempi (e se sono quelli che hai linkato: non li ho capiti).
Grazie per la disponibiletà e pazienza
[Kendall]
05-03-2014, 21:20
Se devi fare più confronti perché non ti salvi tutti i caratteri dei file in un buffer in memoria e poi lavori su quello? È sicuramente più efficiente.
Inviato dal mio Nexus 5 utilizzando Tapatalk
Daniels118
06-03-2014, 07:35
;40819499']Se devi fare più confronti perché non ti salvi tutti i caratteri dei file in un buffer in memoria e poi lavori su quello? È sicuramente più efficiente.
Inviato dal mio Nexus 5 utilizzando Tapatalk
Beh, dipende da quante dati ci sono nel file, immagina un file di 20GB caricato in memoria... non è molto efficiente, ovviamente dipende dall'applicazione, ma comunque aggirare un problema non vuol dire risolverlo.
Daniels118
06-03-2014, 07:42
Mi sermbrava inutile specificare che il file esiste.
Per quanto riguarda la corretta applicazione della lettura di file, potresti guidarmi tu con tuoi esempi (e se sono quelli che hai linkato: non li ho capiti).
Grazie per la disponibiletà e pazienza
Ti posso scrivere la struttura, poi devi inserirlo tu nel programma.
Metodo convenzionale:
in1.open("1.txt");
in1>>fr;
while (!in1.eof()) {
// elaborazione di fr
in1>>fr;
}
Metodo comodo (non l'ho mai provato, ma dovrebbe funzionare):
in1.open("1.txt");
while (in1>>fr) {
// elaborazione di fr
}
[Kendall]
06-03-2014, 08:54
Beh, dipende da quante dati ci sono nel file, immagina un file di 20GB caricato in memoria... non è molto efficiente, ovviamente dipende dall'applicazione, ma comunque aggirare un problema non vuol dire risolverlo.
Gli ho consigliato un possibile e performante approcio al suo problema.
È chiaro che bisogna poi vedere la sua reale situazione, quindi tutte le variabili al contorno del suo caso (che non conosciamo, se non che sta confrontando due generici file di testo).
La dimensione è chiaramente una variabile da prendere in considerazione, ma per quel che ne sai e ne sappiamo quel file può essere di pochi byte come di GB (anche se dubito sia il suo caso, trattandosi di un file di testo :) ).
Daniels118
06-03-2014, 12:23
Che i dati siano pochi nel caso specifico lo sospetto anch'io, ma preferisco che quando si incontra un problema lo si risolva, e solo dopo si cerchi un'eventuale soluzione migliore, soprattutto quando il problema riguarda un'operazione comune come la lettura di un file.
Ora Carmine01 mi scaglierà contro mille fatture, ma credo sono convinto che questo sia il modo corretto di operare, altrimenti gli consiglierei un paio di comandi unix e risolverebbe con una riga di codice :)
Carmine01
06-03-2014, 13:13
Kendall
I file non sono certo grandi 2GB (anche se per elaborare tutto ci mette 3 minuti).. XD quindi il tuo è un consiglio molto valido, ma come dice Daniels118, i problemi DEVONO RISOLVERSI.
Ora, Daniels, non ti maledico, anzi.. ma ti esorto a guardare il codice che rispetta cio che hai scritto, il problema che non hai considerato è che mi servono 3 file FSTREAM (di cui 2 IN e 1 OUT) che lavorano simultaniamente.
Quindi:
è sintatticamente corretto il mio, dal tuo punto di vista? se non lo è, dove sbaglio??
Daniels118
06-03-2014, 13:40
La sintassi è corretta, se non lo fosse la compilazione andrebbe male, quello che non è corretto è la logica, vediamo perché.
Il metodo ios::eof è equivalente alla funzione c feof di cui riporto uno stralcio della documentazione che puoi trovare qui: http://www.cplusplus.com/reference/cstdio/feof/
This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file.
Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point.
Tradotto in sintesi: la fine del file viene rilevata quando si cerca di leggere dopo la fine del file. Anche se la posizione del cursore punta già alla fine del file, questa viene rilevata solo dopo aver effettuato una lettura in quel punto.
Ora consideriamo il tuo algoritmo di lettura:
open(filename)
while (! eof) {
leggi
elabora
}
Nel tuo algoritmo verifichi prima se il file è finito, poi leggi una riga e poi la elabori; tuttavia, dal momento che la fine del file viene rilevata solo dopo aver effettuato un'ulteriore lettura, una volta letta l'ultima riga eof restituirà comunque false, effettuerai una lettura ed elaborerai la riga, ma in realtà non hai letto nulla, quindi elaborerai qualcosa di "sporco".
Utilizzando invece questo algoritmo, il controllo della fine del file avviene sempre dopo la lettura:
open(filename)
leggi
while (! eof) {
elabora
leggi
}
Una lettura oltre la fine del file farà in modo che eof restituisca true e l'elaborazione non verrà eseguita.
L'algoritmo può essere applicato ad entrambi i file innestandone uno identico dove c'è scritto "elabora".
Ovviamente tutto il discorso che ho fatto si applica solo per la lettura.
PS. non è che "non ho considerato", è che voglio fornirti le basi e lasciare che sia tu ad applicarle.
AnonimoVeneziano
07-03-2014, 19:02
Beh, dipende da quante dati ci sono nel file, immagina un file di 20GB caricato in memoria... non è molto efficiente, ovviamente dipende dall'applicazione, ma comunque aggirare un problema non vuol dire risolverlo.
mmap ....
Daniels118
07-03-2014, 21:10
Beh, mmap consentirebbe di ottimizzare il caricamento in memoria rendendolo progressivo, ma resta di fatto che se il file ha una dimensione maggiore della memoria disponibile il sistema deve paginare, andando di fatto a lavorare su disco.
Ovviamente come nella maggior parte dei casi la soluzione migliore sta nel mezzo e una corretta analisi del problema consente di adottare la soluzione più performante.
AnonimoVeneziano
08-03-2014, 10:25
Beh, mmap consentirebbe di ottimizzare il caricamento in memoria rendendolo progressivo, ma resta di fatto che se il file ha una dimensione maggiore della memoria disponibile il sistema deve paginare, andando di fatto a lavorare su disco.
Ovviamente come nella maggior parte dei casi la soluzione migliore sta nel mezzo e una corretta analisi del problema consente di adottare la soluzione più performante.
mmap su un sistema a 64bit e' semplicemente il sistema più semplice ed efficiente. Non rischi mai di finire la VM anche con file molto grossi, le fasi di lettura sono gestite in kernel space, e quindi piu' veloci, il codice del programma si pulisce molto di tutte le varie letture da file e il kernel e' in genere ottimizzato parecchio per rendere una mmap il piu' veloce possibile perche' e' molto usata dai database. L' unico caso in cui non la userei sono sistemi a 32 bit dove so che dovrò leggere file piu' grossi di 1GB. (Ma ormai i sistemi a 32 bit sono in via di estinzione)
Carmine01
08-03-2014, 10:46
mi sento molto stupido, adesso.
Sistemata l'operazione basilare del corretto lavoro su file.
Resta il problema che non mi viene rilevato il file "1.txt" PER NON SO QUALE MOTIVO.
Ho provato a usare una variabile ifstream apposita, ho provato a sostituire il file e variarlo anche nei contenuti ma mi da lo stesso errore..
Grazie per la risposta, a tutti!!
Daniels118
08-03-2014, 11:02
mmap su un sistema a 64bit e' semplicemente il sistema più semplice ed efficiente. Non rischi mai di finire la VM anche con file molto grossi, le fasi di lettura sono gestite in kernel space, e quindi piu' veloci, il codice del programma si pulisce molto di tutte le varie letture da file e il kernel e' in genere ottimizzato parecchio per rendere una mmap il piu' veloce possibile perche' e' molto usata dai database. L' unico caso in cui non la userei sono sistemi a 32 bit dove so che dovrò leggere file piu' grossi di 1GB. (Ma ormai i sistemi a 32 bit sono in via di estinzione)
Quanto dici è perfettamente in accordo con le mie precedenti affermazioni, comunque ciò non toglie che un algoritmo ottimizzato consente di avere prestazioni ancora migliori, per questo sono stati inventati mille tipi di indici, tablespaces e chi più ne ha più ne metta.
Daniels118
08-03-2014, 11:05
mi sento molto stupido, adesso.
Sistemata l'operazione basilare del corretto lavoro su file.
Resta il problema che non mi viene rilevato il file "1.txt" PER NON SO QUALE MOTIVO.
Ho provato a usare una variabile ifstream apposita, ho provato a sostituire il file e variarlo anche nei contenuti ma mi da lo stesso errore..
Grazie per la risposta, a tutti!!
Posta il codice aggiornato così vediamo se ci sono altri errori.
Fai anche molta attenzione ai percorsi dei file, i percorsi relativi fanno riferimento alla workdir, che per i programmi lanciati con doppio click è la stessa dove si trova il file eseguibile, ma se vengono lanciati da shell è la directory visualizzata sul prompt.
Carmine01
08-03-2014, 15:54
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "D:\Programmi\Dev\Carminefunz.cpp"
using namespace std;
const int dimstring=1000;
int main(){
ifstream in1, in2, tmp;
ofstream ou;
char fr[dimstring], temp[dimstring];
bool idem=false;
int righi1=0, righi2=0;
cout<<"\nRinomina il file di testo che possiede tutti gli elementi utili al confronto chiamandolo:\n\"1.txt\" oppure \"1\"\nA seconda se (rispettivamente) le estensioni sono visibili o meno.\n\nRinomica il secondo file in cui POTREBBERO essere mancaze rispetto al primo:\n\"2.txt\" oppure \"2\"";
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("2.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 2/2.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi2++; tmp>>fr;}
tmp.close();
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("1.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 1/1.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi1++; tmp>>fr;}
tmp.close();
in1.open("1.txt");
ou.open("risultati_assenti_in_2.txt");
in2.open("2.txt");
in1>>fr;
while(!in1.eof()) {
//cout<<"\nPRENDO fr: "<<fr;
// in2.open("2.txt");
in2.seekg(0, ios::beg);
idem=false;
//if (!in2.eof()) cout<<"\nENTRA";
//fa il confronto di tutti i righi tranne l'ultimo (gl'impedisco di "arrivare alla fine")
in2>>temp;
while(!in2.eof()) {
//cout<<"\nPRENDO temp: "<<temp;
if (!strcmp(fr, temp)) {
idem=true;
//cout<<"\nVERO";
break;
}
in2>>temp;
}
in1>>fr;
if (idem==false) {ou<<fr<<endl;/* cout<<"\nSCRITTO: "<<fr;*/}
// in2.close();
}
ou.close();
in1.close();
in2.close();
}
Ho provato anche a "far correre il tmp" e andare avanti fino al "in1.open" ma da cmq l'errore sottocondizione di "in1"
Ho provato anche mettendolo nell'unita C:\ ma niente da fare
AnonimoVeneziano
10-03-2014, 12:34
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "D:\Programmi\Dev\Carminefunz.cpp"
using namespace std;
const int dimstring=1000;
int main(){
ifstream in1, in2, tmp;
ofstream ou;
char fr[dimstring], temp[dimstring];
bool idem=false;
int righi1=0, righi2=0;
cout<<"\nRinomina il file di testo che possiede tutti gli elementi utili al confronto chiamandolo:\n\"1.txt\" oppure \"1\"\nA seconda se (rispettivamente) le estensioni sono visibili o meno.\n\nRinomica il secondo file in cui POTREBBERO essere mancaze rispetto al primo:\n\"2.txt\" oppure \"2\"";
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("2.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 2/2.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi2++; tmp>>fr;}
tmp.close();
//conta i righi di un file e verifica dell'apertura dello stesso.
tmp.open("1.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 1/1.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi1++; tmp>>fr;}
tmp.close();
in1.open("1.txt");
ou.open("risultati_assenti_in_2.txt");
in2.open("2.txt");
in1>>fr;
while(!in1.eof()) {
//cout<<"\nPRENDO fr: "<<fr;
// in2.open("2.txt");
in2.seekg(0, ios::beg);
idem=false;
//if (!in2.eof()) cout<<"\nENTRA";
//fa il confronto di tutti i righi tranne l'ultimo (gl'impedisco di "arrivare alla fine")
in2>>temp;
while(!in2.eof()) {
//cout<<"\nPRENDO temp: "<<temp;
if (!strcmp(fr, temp)) {
idem=true;
//cout<<"\nVERO";
break;
}
in2>>temp;
}
in1>>fr;
if (idem==false) {ou<<fr<<endl;/* cout<<"\nSCRITTO: "<<fr;*/}
// in2.close();
}
ou.close();
in1.close();
in2.close();
}
Ho provato anche a "far correre il tmp" e andare avanti fino al "in1.open" ma da cmq l'errore sottocondizione di "in1"
Ho provato anche mettendolo nell'unita C:\ ma niente da fare
Potrei avere capito qual'e' il tuo problema ...
Come lanci il programma?
Carmine01
10-03-2014, 17:41
sia da compilazione del DEV-CPP
oppure aprendo l'eseguibile generato
AnonimoVeneziano
11-03-2014, 18:29
sia da compilazione del DEV-CPP
oppure aprendo l'eseguibile generato
Se non lo lanci da console, ma lo lanci da DEV-CPP o cliccando ci sopra la cartella di lavoro corrente potrebbe non essere settata alla directory in cui l'eseguibile e' contenuto. Prova a lanciarlo da console, muovendoti fino alla directory in questione e poi lancialo da li e vedi se funziona.
Carmine01
12-03-2014, 11:19
L'eseguibile e i file si trovano nella stessa cartella (desktop).
Ma, 2.txt lo trova e lo apre, 1.txt no.
Questo è assurdo xD
Provo a reninstallare il Dev... magari..funziona!!
Ho appena fatto un esperimento.
Nel codice, ho scambiato l'ordine di apertura file.
Praticamente il primo file che chiamo viene visto, il secondo NO!!
Infatti:
tmp.open("2.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 2/2.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi2++; tmp>>fr;}
tmp.close();
tmp.open("1.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 1/1.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi1++; tmp>>fr;}
tmp.close();
NON mi trova 1.txt
tmp.open("1.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 1/1.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi1++; tmp>>fr;}
tmp.close();
tmp.open("2.txt");
if (tmp.fail()) {cout<<"\n\n\nIL FILE 2/2.txt MANCA.\n"; system("pause"); exit(1);}
tmp>>fr;
while (!tmp.eof()) {righi2++; tmp>>fr;}
tmp.close();
così non mi trova 2.txt
Ho anche prvato a cambiare cartella, nome file, usare una ifstream diversa ad usare un nuovo file di testo (magari il vecchio era corrotto somewhere).. ma niente.
Ci stiamo avvicinando sempre di più :eek: :eek: :eek:
Daniels118
12-03-2014, 19:15
Ops, sbagliato... scusate
Carmine01
13-03-2014, 00:35
Ops, sbagliato... scusate
:boh: :mano:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.