Estrazione testo da file
con la seguente funzione intendo estrarre il testo contenuto nei file di una directory scelta da input e inserirlo in una serie di tabelle hash...
il tutto funziona ad eccezione del push_back...
mi da un errore del tipo:
[img]http://img838.imageshack.us/i/catturazk.jpg/[/img] non so quale sia il motivo...fatto sta che se dichiaro static l'oggetto tab allora se la cartella contiene un solo file lo carica correttamente, ma se ci sono più file nella cartella mi si blocca con un'altra finestra di errore...
Files è di tipo vector> e tabs è un typedef di tabellahash
//funzione di acquisizione file... void functionAdd() { WIN32_FIND_DATA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; char DirSpec[MAX_PATH]; // directory specification do { cout << "Inserisci un Path valido: "; cin >> DirSpec; strcat_s(DirSpec, "\\*"); hFind = FindFirstFile(DirSpec, &FindFileData); }while(hFind == INVALID_HANDLE_VALUE); do { // If this filename is NOT a directory if( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { char dir2[MAX_PATH]; for(int i = 0; i < MAX_PATH; i++) { dir2[i] = DirSpec[i]; if(dir2[i] == '*') dir2[i] = '\\'; } strcat_s(dir2, FindFileData.cFileName); ifstream is(dir2, ios::in); if (!is.good()) cout << "Errore in apertura di: " << FindFileData.cFileName << endl; //controllo apertura file else { tabs t = leggiFile(is, FindFileData); if(t.getNel()) Files.push_back(t); } is.close();//chiudi il collegamento al file }//si sposta al file successivo all'interno della stessa directory } while( FindNextFile(hFind, &FindFileData) ); FindClose(hFind);//interrompe l'Handle al file... } tabs leggiFile(istream & is, WIN32_FIND_DATA FindFileData) { tabs tab; tab.setNomeFile(FindFileData.cFileName); string s; int n = 0;//controlla se sono state inserite parole o meno... while(getline(is, s, '\n')) {//acquisisci fino alla fine della riga Tokenizer st(s); string token; while((token = st.next()) != "")tab.ins(token); s.clear();//svuota la stringa s } AddEffect++;//segna quante add sono state effettuate return tab; }
il tutto funziona ad eccezione del push_back...
mi da un errore del tipo:
[img]http://img838.imageshack.us/i/catturazk.jpg/[/img] non so quale sia il motivo...fatto sta che se dichiaro static l'oggetto tab allora se la cartella contiene un solo file lo carica correttamente, ma se ci sono più file nella cartella mi si blocca con un'altra finestra di errore...
Files è di tipo vector
Risposte
Non so cosa tu faccia esattamente; comunque se ti dà access violation in generale significa che stai cercando di accedere (leggere/scrivere) su qualcosa (file/directory) che è già aperto da un'altra parte. Poichè hai accvio sulla "lettura del percorso" significa che findfile ha accesso esclusivo (lock) su quel path, e probabilmente push_back legge/scrive il path.
no ma push_back() ne legge ne scrive il path...il problema è che la struttra dati che uso "FILES" è un vector> e mi sa che c'è qualcosa che non va tra distruttori e costruttori nel momento dell'uscita dalla funzione...se nel path che dichiaro si trova un solo file lo ascquisisce e il problema me lo da al riutilizzo del vector riempito, se invece ci sono più file allora già al push_back mi segnala l'errore...tabs è di tipo tabellahash
Ho fatto una preanalisi, ma c'è qualcosa che non conosco (non ho capito): l'errore avviene al momento della chiamata a FindNextFile() oppure... dove?
io credo che avvenga nel findNextFile() come hai detto tu...ma nel caso di un solo file lo fa acquisire ed in un successivo riutilizzo del vector mi da un errore di bad_alloc()...non so se le due cose sono collegate o meno...
comunque ho inserito un cout subito prima di finenextfile() e diciamo che il do while si ferma dopo 4 giri...stranamente ho notato che anche se nella cartella c'è un solo file allora il ciclo lo esegue lo stesso 4 volte -.-
L'errore a me sembra dovuto ad un accesso non consentito su un file. Hai provato a stampare le informazioni del file che leggi in modo da capire su che file hai problemi e perché? Il quarto file non sarà probabilmente una cartella, ma qualche altro tipo di file su cui non hai accesso in lettura (o qualcosa di simile). Puoi anche provare a far girare il tuo programma da amministratore per vedere se il problema è effettivamente quello.
no non è quello perchè me lo fa lo stesso anche con file .txt da me creati o in caso di avvio come amministratore...
Ma hai provato a fare un debug dettagliato? Andando avanti un operazione per volta usando il debbugger invece dei cout? In modo da capire meglio in quale riga del codice va in crash.
ok ho fatto il debug istruzione per istruzione e nel momento in cui digito il path esce la finestra di errore ma mi fa comunque andare avanti, dopo di che nonostante la cartella contenga un solo file effetta due cicli del do while e solo al terzo verifica la condizione dell'if ed apre il file dopo di che effettua un altro ciclo ed esce dalla funzione in modo regolare...ma non riesco a capire come possa succedere ciò!
facendo un debug più dettagliato sono riuscito a capire l'istruzione precisa in cui avviene l'errore ...
io ho un vector>
dove una tabella hash nel private ha come dati membro tra gli altri una lista in questo caso di string e un vector>
l'errore si verifica nel momento in cui viene chiamata la funzione di inizializzazione del vettore di lista che è questa....
io ho un vector
dove una tabella hash nel private ha come dati membro tra gli altri una lista in questo caso di string e un vector
l'errore si verifica nel momento in cui viene chiamata la funzione di inizializzazione del vettore di lista
void init( int iMn, int iMx) { assert (iMx>=iMn); elementi = new T[iMx-iMn+1]; <------ riga dell'errore!!! vimin = iMn; vimax = iMx; }
Cosa fa la funzione setNomeFile di tabs?
assegna al membro string nomeFile il valore mandato come argomento della funzione.
forse stavo pensando che l'operatore NEW non riesce ad allocare memoria dinamica per una lista...visto che elementi è un puntatore ad una lista
"Riuzaki":
assegna al membro string nomeFile il valore mandato come argomento della funzione.
Copiato o assegnato?
Pensavo ad una cosa del genere: il membro cFileName della WIN32_FILE_DATA è un char[] auto, locale (rispetto alla funzione dove l'hai definito). Poniamo punti alla memoria in posizione X. Potrebbero succedere due cose:
- il valore originale X viene sovrascritto;
- la struttura viene sovrascritta in quanto scrivi da posizione X in poi.
Fai il debug passo passo, guarda quanto vale il puntatore prima della chiamata della tua leggiFile e subito dopo.
allora la variabile findfiledata ad inizio della funzione ha come indirizzo 0x00000010 mentre dopo il primo ciclo di while diventa 0x00000020 e come detto in precedenza il programma si blocca nella chiamata dell'operatore new nel costruttore del vector...
"That'sWindows"
Ok, visto che ti serve solo il nome del file nella leggiFile, fa una copia del membro della struttura
- definisci una copia
char nomeF[MAX_PATH];
- ci copi sopra il nome prima della chiamata a leggifile
strncpy(nomeF, FindFileData.cFileName, MAX_PATH);
- passi la copia a leggiFile (e modifichi la funzione ovviamente)
PS. Controlla poi col debugger che non ti perda anche 'sto indirizzo...

Ok, visto che ti serve solo il nome del file nella leggiFile, fa una copia del membro della struttura
- definisci una copia
char nomeF[MAX_PATH];
- ci copi sopra il nome prima della chiamata a leggifile
strncpy(nomeF, FindFileData.cFileName, MAX_PATH);
- passi la copia a leggiFile (e modifichi la funzione ovviamente)
PS. Controlla poi col debugger che non ti perda anche 'sto indirizzo...
niente da fare -.- ho modificato addirittura cosi:
ma niente
ma niente
void functionAdd() { WIN32_FIND_DATA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; char DirSpec[10]; // directory specification do { cout << "Inserisci un Path valido senza \"\\\" alla fine: "; cin >> DirSpec; strcat(DirSpec, "\\*"); hFind = FindFirstFile(DirSpec, &FindFileData); }while(hFind == INVALID_HANDLE_VALUE); do { // If this filename is NOT a directory if( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { char dir2[10]; for(int i = 0; i < 10; i++) { dir2[i] = DirSpec[i]; if(dir2[i] == '*') dir2[i] = '\0'; } strcat(dir2, FindFileData.cFileName); ifstream is(dir2, ios::in); if (is.fail()) cout << "Errore in apertura di: " << FindFileData.cFileName << endl; //controllo apertura file else { tabs t = leggiFile(is, FindFileData.cFileName); if(t.getNel()) { Files.push_back(t); AddEffect++;//segna quante add sono state effettuate } } is.close();//chiudi il collegamento al file }//si sposta al file successivo all'interno della stessa directory cout << "punto interruzione\n"; } while( FindNextFile(hFind, &FindFileData) ); FindClose(hFind);//interrompe l'Handle al file... } tabs leggiFile(istream & is,string f) { tabs tab; tab.setNomeFile(f); string s; int n = 0;//controlla se sono state inserite parole o meno... while(getline(is, s, '\n')) {//acquisisci fino alla fine della riga Tokenizer st(s); string token; while((token = st.next()) != "")tab.ins(token); s.clear();//svuota la stringa s } return tab; }
Quella che hai fatto non è la copia della stringa cFileName da un'altra parte... semplicemente hai cambiato nome del parametro. Devi fare una cosa del genere
void functionAdd() { WIN32_FIND_DATA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; char DirSpec[10]; // directory specification do { cout << "Inserisci un Path valido senza \"\\\" alla fine: "; cin >> DirSpec; strcat(DirSpec, "\\*"); hFind = FindFirstFile(DirSpec, &FindFileData); }while(hFind == INVALID_HANDLE_VALUE); do { // If this filename is NOT a directory if( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { char dir2[10]; for(int i = 0; i < 10; i++) { dir2[i] = DirSpec[i]; if(dir2[i] == '*') dir2[i] = '\0'; } strcat(dir2, FindFileData.cFileName); ifstream is(dir2, ios::in); if (is.fail()) cout << "Errore in apertura di: " << FindFileData.cFileName << endl; //controllo apertura file else { char f[MAX_PATH]; // abbastanza per il nome strncpy(f, FindFileData.cFileName, MAX_PATH); tabs t = leggiFile(is, f); if(t.getNel()) { Files.push_back(t); AddEffect++;//segna quante add sono state effettuate } } is.close();//chiudi il collegamento al file }//si sposta al file successivo all'interno della stessa directory cout << "punto interruzione\n"; } while( FindNextFile(hFind, &FindFileData) ); FindClose(hFind);//interrompe l'Handle al file... } tabs leggiFile(istream & is,string f) // oppure leggiFile(istream &is, char *f) { tabs tab; tab.setNomeFile(f); string s; int n = 0;//controlla se sono state inserite parole o meno... while(getline(is, s, '\n')) {//acquisisci fino alla fine della riga Tokenizer st(s); string token; while((token = st.next()) != "")tab.ins(token); s.clear();//svuota la stringa s } return tab; }
purtroppo l'errore resta -.- non so più che fare....
Il solito errore..? Strano, non vedo dove la struttura originale possa venir sovrascritta. O forse un acces violation generico? Perché allora è proprio la funzione setNomeFile che, da qualche parte, sovrascrive un puntatore (nel punto che evidentemente hai identificato prima). Se fosse così, basterebbe fare la copia all'interno della funzione (ovvero passare cFileName, definire f[] in leggiFile e copiarci sopra cFileName con strncpy prima di richiamare setNomeFile).
Se non funziona, a 'sto punto rimando a domattina che magari a freddo ci viene in mente qualche workaround.
Se non funziona, a 'sto punto rimando a domattina che magari a freddo ci viene in mente qualche workaround.