Premessa: quel che propongo NON e' un esempio di come fare o non fare, perché non ho la formazione per dare esempi di sorta. NON è neppure "pappa pronta", perché il mio codice sarebbe con ogni probabilità schifato in qualsiasi ambito scolastico/accademico, essendo un codice un po'... alla come viene, viene. Inutilizzabile. Si tratta solo dell'esito di un'attività di intrattenimento suggeritami dal tuo intervento. Prendilo per quel che è (potrebbero esserci errori anche madornali). Detto questo...
Ho messo insieme una classe che permette di ottenere con UNA RIGA di codice un oggetto che fornisce un elenco dei file presenti in una cartella data (ignorando le sottocartelle, però
.
La classe è molto limitata da una quantità di punti di vista. Per dirne una, in caso di errori si limita sempre allo stesso comportamento - lanciare un'eccezione di tipo bool e valore false. Per dirne un'altra, formula le sue stringhe come array di char (da 1 byte), in stile C.
Se si crea un oggetto così...
ElencoFile ef( "C:\Users\NomeUtente\Desktop" );
...l'oggetto viene "popolato" con un elenco dei percorsi e nomi dei file contenuti nella cartella del Desktop di NomeUtente.
Se lo si crea così...
ElencoFile ef;
...l'oggetto viene "popolato" con un elenco dei percorsi e nomi dei file contenuti nella
working directory (cartella corrente).
Una volta creato l'oggetto, preferibilmente includendone la creazione in un blocco try/catch per intercettare le eventuali eccezioni di tipo bool, si può conoscere la quantità dei file contenuti nell'elenco con una chiamata a ef.TotaleFile() e si può accedere ai singoli percorso+nome di ogni file con chiamate a ef.NomeFile(indice) purché "indice" sia un valore compreso tra 0 e il totale dei file meno uno. E' anche possibile abbinare un oggetto già esistente a una nuova cartella, con ef.AcquisisciElencoDaCartella().
file main.c di esempio
#include <cstdio>
#include "elencofile.h"
int main() {
try {
ElencoFile ef; // elenca i file presenti nella working directory
for( unsigned int i=0; i<ef.TotaleFile(); ++i )
printf( "%s\n", ef.NomeFile(i) );
return 0;
} catch( ... ) {
puts( "Errore!" );
return 1;
}
}
file elenco_file.h
#ifndef ELENCOFILE_H
#define ELENCOFILE_H
#include <windows.h>
#include <cstdlib>
#include <cstring>
class ElencoFile {
public:
ElencoFile( const char *cartella = NULL );
virtual ~ElencoFile();
ElencoFile(const ElencoFile& other);
ElencoFile& operator=(const ElencoFile& other);
bool AcquisisciElencoDaCartella( const char *cartella );
unsigned int TotaleFile( void ) const { return tf; }
const char *NomeFile( unsigned int indice ) const;
protected:
private:
char **ef; // ef: elenco file
unsigned int tf; // tf: totale file
size_t dd; // dd: dimensioni dati
char *DuplicaPercorso( const char *percorso );
bool AnalizzaContenutoCartella(
const char *cartella, unsigned int *qFile, size_t *dDati );
char **CreaElencoDaCartella(
const char *cartella, unsigned int qFile, size_t dDati );
};
#endif // ELENCOFILE_H
file elenco_file.cpp
#include "elencofile.h"
ElencoFile::ElencoFile( const char *cartella ) {
ef = NULL;
tf = 0;
dd = 0;
if( !AcquisisciElencoDaCartella(cartella) ) throw false;
}
ElencoFile::~ElencoFile() {
if( ef ) delete[] ef;
}
ElencoFile::ElencoFile(const ElencoFile& other) {
ef = NULL;
tf = 0;
dd = 0;
*this = other;
}
ElencoFile& ElencoFile::operator=(const ElencoFile& rhs) {
if (this == &rhs) return *this; // handle self assignment
if( rhs.ef ) {
void *tmp = malloc( rhs.dd );
if( NULL == tmp ) throw false;
memcpy( tmp, rhs.ef, rhs.dd );
if( ef ) free( ef );
ef = (char**)tmp;
tf = rhs.tf;
dd = rhs.dd;
}
return *this;
}
bool ElencoFile::AcquisisciElencoDaCartella( const char *cartella ) {
char *dupPercCart = NULL;
bool ok = false;
if( (dupPercCart=DuplicaPercorso(cartella)) ) {
unsigned int tfTmp = 0;
size_t ddTmp = 0;
if( AnalizzaContenutoCartella(dupPercCart,&tfTmp,&ddTmp) ) {
char **efTmp = CreaElencoDaCartella( dupPercCart, tfTmp, ddTmp );
if( NULL != efTmp ) {
if( ef ) free( ef );
ef = efTmp;
tf = tfTmp;
dd = ddTmp;
ok = true;
}
}
free( (void*)dupPercCart );
}
return ok;
}
const char *ElencoFile::NomeFile( unsigned int indice ) const {
if( ef && indice<tf )
return ef[indice];
else return NULL;
}
// privata
char *ElencoFile::DuplicaPercorso( const char *percorso ) {
char *buff = NULL;
if( NULL==percorso ) {
DWORD dimBuff = GetCurrentDirectory( 0, NULL );
if( (buff=(char*)calloc(dimBuff+4,sizeof(*buff))) ) {
GetCurrentDirectory( dimBuff, buff );
memcpy( buff+dimBuff-1, "\*.*", 5 );
}
}
else {
size_t l = lstrlen( percorso );
if( (buff=(char*)malloc(l+5)) ) {
memcpy( buff, percorso, l );
memcpy( buff+l, "\*.*", 5 );
}
}
return buff;
}
// privata
bool ElencoFile::AnalizzaContenutoCartella(
const char *cartella, unsigned int *qFile, size_t *dDati ) {
if( !cartella || !qFile || !dDati ) return false;
size_t lNomeCartella = lstrlen(cartella)-3;
WIN32_FIND_DATA fd = {0};
HANDLE hnd = NULL;
*qFile = 0;
*dDati = 0;
hnd = FindFirstFile( cartella, &fd );
if( INVALID_HANDLE_VALUE != hnd ) {
if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
while( FindNextFile(hnd,&fd) ) {
if( !(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) ) {
*dDati += sizeof(char*)+lNomeCartella+lstrlen(fd.cFileName)+1;
++(*qFile);
}
}
}
FindClose( hnd );
return true;
}
return false;
}
// privata
char **ElencoFile::CreaElencoDaCartella(
const char *cartella, unsigned int qFile, size_t dDati ) {
if( !cartella ) return NULL;
void *dTmp = calloc( dDati, 1 );
if( !dTmp ) return NULL;
// Lo scopo della gran confusione creata con una pletora di puntatori e cast
// nelle prossime righe, e' inserire tutti i percorsi+nomi dei file in un
// unico blocco di memoria al quale sia possibile accedere come ad un comune
// array di stringhe C. Inutilmente complicato? Puo' darsi. Pasticciato?
// Puo' darsi. Pero' sembra funzionarea a dovere. :)
size_t lPercorso = lstrlen(cartella)-3;
size_t dimPtr = sizeof(char*);
void *y = dTmp;
void *x = ((void*)(((size_t)dTmp)+qFile*dimPtr));
unsigned int i=0;
WIN32_FIND_DATA fd = {0};
HANDLE hnd = FindFirstFile( cartella, &fd );
if( INVALID_HANDLE_VALUE != hnd ) {
if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
while( FindNextFile(hnd,&fd) && i<qFile ) {
if( !(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) ) {
size_t lNomeFile = lstrlen(fd.cFileName);
memcpy( y, &x, dimPtr );
memcpy( x, cartella, lPercorso );
memcpy( (void*)((size_t)x+lPercorso), fd.cFileName, lNomeFile+1 );
y = (void*)(((size_t)y)+dimPtr);
x = (void*)((size_t)x+lPercorso+lNomeFile+1);
++i;
}
}
}
else {
free( dTmp );
dTmp = NULL;
}
FindClose( hnd );
return (char**)dTmp;
}
return NULL;
}
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.