begin process at 2012 05 30 15:59:22
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C++ & C++ .NET

 > 

Linux

 > 

Fichier & Disque

 > 

récursiviter, lister les répertoires en C++


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

récursiviter, lister les répertoires en C++

mercredi 8 avril 2009 à 03:09:31 | récursiviter, lister les répertoires en C++

panthere007

Hello,
Merci de me lire,
excuser l'indentation des commentaires mai le copier coller déconne
pour le bug c'est simple c'est expliquer aux début du fichier
noter que je débute,depuis peux que je compile avec g++ j'utilise geany comme éditeur.
ce code est fonctionnel hormis le fait qu'il ne fait pas ce que je veux
Curieux il n'y a pas le moyen de coller son code ?
code

#include <iostream>
#include <vector>
#include <string>
#include <dirent.h>
#include <sys/stat.h>
using std::string;
/*
 _______________________________
/______________________________/|
||    Coder par panthere noire   ||
||        liscence GPL v3        ||
|/_____________________________|/

Ce code est destiner a lister le plus rapidement possible.
Les fichier et les répertoire sous linux.
Avec leur atribbus aux complet.
 
*/

/*
Les répertoires ce présente comme ceci.
note: remplacer le ~ par celui de votre utilisateur.
mkdir -p ~/rep_racine/rep1
mkdir -p ~/rep_racine/rep2/sous_rep_2_0
mkdir -p ~/rep_racine/rep2/sous_rep_2_1
mkdir -p ~/rep_racine/rep2/sous_rep_2_2
mkdir -p ~/rep_racine/rep2/sous_rep_2_3
mkdir -p ~/rep_racine/rep3
mkdir -p ~/rep_racine/rep2/sous_rep_2_3/sous_sous_rep2
*
le dernier répertoir n'est pas trouver alors que ceux situer dans ~/rep_racine/rep2/ le son
*/
 
void Full_Search(std::vector<string> &search_full_path,
std::vector<string> &search_rep_name,
std::vector<string> &search_file_name,
std::vector<string> &stat_info,std::string &transfere);                                                //Prototype Full_Search


void Full_Search(std::vector<string> &search_full_path,
std::vector<string> &search_rep_name,
std::vector<string> &search_file_name,
std::vector<string> &stat_info, std::string &transfere)
{

    long number_element;                                                                            //déclaration, nombre d'element
    std::string source_transfere;                                                                    //déclaration, provisoire copie les donnée de la variable
    source_transfere = transfere;                                                                   
    number_element = search_full_path.size() -1;
        std::cout << "DEBUG ----------1: " << number_element << " :----------contien----------: "
         << search_full_path [number_element] << std::endl;
    if (source_transfere != "")
    {
        std::cout << "DEBUG ----------2: " << number_element << " :----------contien----------: "
        << search_full_path [number_element] << std::endl;
        int cmb = source_transfere.length();
        if (source_transfere.substr((cmb- 1), cmb) != "/")
        {
            source_transfere += "/";
            std::cout << "DEBUG ----------3: source_transfere :----------contien----------: "
            << source_transfere << std::endl;
        }
        DIR *InitialRep = opendir(source_transfere.c_str());
        if (InitialRep != NULL)
        {
            struct dirent *SRep;
            while ((SRep = readdir(InitialRep)) != NULL)                                            //tant que le répertoire contient des fichiers
            {
                string FileFound = SRep->d_name;                                                    //definir le fichier (dernier répertoir trouver)
                string PathFound = source_transfere + FileFound;                                    // chemin complet
                if (FileFound != "." && FileFound != "..")
                {   
                    source_transfere = PathFound;
                        FileFound = FileFound + "/";
                        search_full_path.push_back(FileFound);
                        ++number_element;
                        std::cout << "DEBUG ----------4: " << number_element <<
                        " :----------contien----------: " << FileFound << std::endl;
                        std::cout << "DEBUG ----------5: " << number_element <<
                        " :----------contien----------: " << search_full_path [number_element]
                        << std::endl;
                        if (opendir(PathFound.c_str()) != NULL)
                        {
                            std::cout << "DEBUG ----------6: " << number_element <<
                            " :----------contien----------: " << search_full_path [number_element]
                            << std::endl;
                            Full_Search(search_full_path, search_rep_name,
                            search_file_name, stat_info, source_transfere);                            //apelle recusif pour les sous répertoires bug ?
                            std::cout << "DEBUG ----------7: " << number_element
                            << " :----------contien----------: " << search_full_path [number_element]
                            << std::endl;
                        }
                }
                else                                                                                //else uniquement pour le debugage,il est possible de le supprimer
                {
                    std::cout << "DEBUG ----------8: " << number_element <<
                    " :----------contien----------: " << search_full_path [number_element]
                    << std::endl;
                    std::cout << "DEBUG ----------9: " << FileFound << std::endl;
                    std::cout << "DEBUG ----------10: " << transfere << std::endl;
                    std::cout << "DEBUG ----------11:: " << source_transfere << std::endl;
                   
                }
            } //while
        }
        closedir(InitialRep);                                                                        //fermer le repertoire courant
    }
}                                                                                                    //function Full_Search

int main()
{
                                                                                                    //variable
std::vector<std::string> search_full_path;                                                            //retourne un tableau chemin complet de tout les répertoires trouver
std::vector<std::string> search_rep_name;                                                             //repertoir seulement,pas encore utilisée
std::vector<std::string> search_file_name;                                                            //fichier seulement,pas encore utilisée
std::vector<std::string> stat_info;                                                                    //information global sur le répertoir ou le dossier,pas encore utilisée
std::string transfere;                                                                                //variable pour le nom du repertoir en recusiviter, passe en paramettre le répetoire racine.

                                                                                                    //code
                                                                                                   
search_full_path.push_back("/home/taz/rep_racine/");                                                //valeur par defaut,en cour de dévloppment,rarement utiliser
transfere = "/home/taz/rep_racine";
Full_Search(search_full_path, search_rep_name, search_file_name, stat_info,transfere);
std::cout << "nombre d'élément apres execution " << search_full_path.size() << std::endl;            //affiche le nombre d'entrée du tableau
    for (long i = 0; i < search_full_path.size(); ++i )                                             //affiche le contenu du tableaux
    {
        std::cout << search_full_path[i] << std::endl;
    }
std::cout << "affichage terminer" << std::endl;
return 0;
}                                                                                                    // main




mercredi 8 avril 2009 à 15:35:36 | Re : récursiviter, lister les répertoires en C++

rt15

Membre Club Administrateur CodeS-SourceS
Salut,

[quote=panthere007]
Ce code est destiner a lister le plus rapidement possible.
[/quote]

Le plus rapidement possible ?

Alors tu n'emploies pas du tout la bonne méthode.

td::vector<string> -> string est lent. vector est lent. Combiné les deux c'est affreusement lent.

Et imagine que ton répertoire contienne 10000 répertoires ? Tu fait un vector de 10000 strings ?
Tu as une idée de la consommation mémoire ?
Bref, tu n'iras pas bien loin avec ce genre d'algo.

D'une manière générale quand on veut :
1) Récupérer un ensemble d'objets quelconques.
2) Appliquer un algo sur chacun d'entre eux.

Il ne faut pas essayer de lister ces objets puis parcourir ces objets.

Il faut faire le traitement a chaque objet lors du parcourt. C'est infiniment plus efficace.

Mais on voudrait ne pas avoir à réécrire l'algo de parcourt pour tous les traitements possibles.
Le copier coller, c'est mal.

On va donc faire une fonction de parcourt qui prend en argument une fonction (on appelle ça une callback) de traitement.

Comme ça la fonction de parcourt va appeler la fonction de traitement pour tous les élements parcouru.
Sans faire de liste ni autre structure mémoire aussi consommatrice de RAM que lente car allouée dynamiquement.

Voilà un exemple de code.

C'est du C. Ou du C++. Comme tu veux. Mais pour faire du "plus rapidement possible", je t'invite vivement à oublier le C++.

#include <stdio.h>
#include <dirent.h>
#include <string.h>
 
/* Fonction callback appelée lors de l'énumération */
typedef int (*enum_dir_callback)(char *lpDirPath);

/*
 * Utilisée par EnumDir pour pouvoir transmettre un buffer en paramètre
 * et ainsi ne pas surchrager la pile.
 */
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback, char* lpBuffer)
{
  DIR *lpDir;               /* Le répertoire courant      */
  struct dirent *lpChild;   /* Un fils du répertoire      */
  int bContinue;            /* Continuer l'énumération ?  */
   
  bContinue = 1;
  lpDir = opendir(lpDirPath);

  /* Si c'est un répertoire */
  if (lpDir)
  {
    /* Appel de la fonction utilisateur */
    if (! lpCallback(lpDirPath))
      bContinue = 0;
    else
    {
      /* On récupère . et .. */
      readdir(lpDir);
      readdir(lpDir);

      /* Pour tous les fils */
      while (1)
      {
        lpChild = readdir(lpDir);
        if (! lpChild) break;

        /* Construction d'un chemin complet vers le fils */
        strcpy(lpBuffer, lpDirPath);
        strcat(lpBuffer, "/");
        strcat(lpBuffer, lpChild->d_name);

        /* Appel récursif */
        if (! EnumDirInternal(lpBuffer, lpCallback, lpBuffer))
        {
          bContinue = 0;
          break;
        }
      }
    }
    closedir(lpDir);
  }
  return bContinue;
}

/*
 * Appelle lpCallback pour lpDirPath et tous ses sous répertoires.
 * Arrête l'énumération si lpCallback renvoie 0.
 */
int EnumDir(char *lpDirPath, enum_dir_callback lpCallback)
{
  char lpFullPath[4096];

  return EnumDirInternal(lpDirPath, lpCallback, lpFullPath);
}

/*
 * Notre fonction qui sera appelée pour tous les répertoires.
 */
int DisplayDir(char *lpDirPath)
{
  printf("%s\n", lpDirPath);
  return 1;
}

int main(void)
{
  /* On appelle DisplayDir pour tous les sous répertoires de . */
  EnumDir(".", DisplayDir);

  return 0;
}


jeudi 9 avril 2009 à 00:54:10 | Re : récursiviter, lister les répertoires en C++

panthere007

Merci pour ta réponse très constructives :)

Je ne connaissait pas les callback, je vai me panchez dessus

j'ai essayer ton code telle qu'elle , 2 bug voici la première erreur:

surf_find_file_main.cpp: In function 'int main()':
surf_find_file_main.cpp:80: warning: deprecated conversion from string constant to 'char*'
./
./.

la 2eme j'ai change le chemin dans le main par /home/user/rep_racine user étant l'utilisateur et j'obtien
line 10:  5329 Erreur de segmentation


note je compile avec g++ ton code rassemble surtout a du C et pas du C++ (excuse pour la confusion c'est lier aux fait que j'utilise cout et pas printf.
Avec quoi l'a tu compiler ? gcc ?

Merci pour ta réponse :)
jeudi 9 avril 2009 à 10:09:00 | Re : récursiviter, lister les répertoires en C++

rt15

Membre Club Administrateur CodeS-SourceS
Avec quoi l'a tu compiler ? gcc ?

Avec les deux en fait.

warning: deprecated conversion from string constant to 'char*'

Mais je n'ai pas eu ce warning. D'après le net, il n'apparait pas sur des versions anciennes. Il est en fait dû au fait que mon "." passé en paramètre de EnumDir est en lecture seule, et donc qu'il ne peut pas être passé en paramètre d'une fonction qui attend un char*. Il faut changer une ou deux signatures en ajoutant const.

line 10:  5329 Erreur de segmentation

Probablement un dépassement des 4096 caractères du tampon. Non pas que tu ais (Ou pas) un chemin de 4096 caractères dans ton home, il y a un bug dans mon source.

En effet, lors de l'appel à EnumDirInternal(lpBuffer, lpCallback, lpBuffer), lpBuffer était modifié pour ajouté un fils, ce qui modifiait aussi le lpDirPath puisqu'ils sont les mêmes lors de cette appel. Bilan cela concaténait le fils 1 avec le fils 2 et ainsi de suite. Donc ça ne listait pas la moitié des répertoires et ça faisait des chemins beaucoup trops longs -> d'où l'erreur de segmentation je pense.

Donc il faut remonter d'un répertoire en sortie d'appel à EnumDirInternal.

Voilà qui devrait aller mieux :

#include <stdio.h>
#include <dirent.h>
#include <string.h>
 
/* Fonction callback appelée lors de l'énumération */
typedef int (*enum_dir_callback)(const char *lpDirPath);

/*
 * Utilisée par EnumDir pour pouvoir un premier caractère non const.
 */
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback)
{
  DIR *lpDir;               /* Le répertoire courant      */
  struct dirent *lpChild;   /* Un fils du répertoire      */
  int bContinue;            /* Continuer l'énumération ?  */
   
  bContinue = 1;
  lpDir = opendir(lpDirPath);
 
  /* Si c'est un répertoire */
  if (lpDir)
  {
    /* Appel de la fonction utilisateur */
    if (! lpCallback(lpDirPath))
      bContinue = 0;
    else
    {
      /* On récupère . et .. */
      readdir(lpDir);
      readdir(lpDir);

      /* Pour tous les fils */
      while (1)
      {
        lpChild = readdir(lpDir);
        if (! lpChild) break;

        /* Construction d'un chemin complet vers le fils */
        strcat(lpDirPath, "/");
        strcat(lpDirPath, lpChild->d_name);

        /* Appel récursif */
        if (! EnumDirInternal(lpDirPath, lpCallback))
        {
          bContinue = 0;
          break;
        }
        /* Récupération du parent */
        strrchr(lpDirPath, '/')[0] = '\0';
      }
    }
    closedir(lpDir);
  }
  return bContinue;
}

/*
 * Appelle lpCallback pour lpDirPath et tous ses sous répertoires.
 * Arrête l'énumération si lpCallback renvoie 0.
 */
int EnumDir(const char *lpDirPath, enum_dir_callback lpCallback)
{
  char lpPath[4096];

  strcpy(lpPath, lpDirPath);
  return EnumDirInternal(lpPath, lpCallback);
}

/*
 * Notre fonction qui sera appelée pour tous les répertoires.
 */
int DisplayDir(const char *lpDirPath)
{
  printf("%s\n", lpDirPath);
  return 1;
}

int main(void)
{
  /* On appelle DisplayDir pour tous les sous répertoires de . */
  EnumDir("/home/brbo/dml-mapper", DisplayDir);

  return 0;
}

vendredi 10 avril 2009 à 23:26:50 | Re : récursiviter, lister les répertoires en C++

panthere007

merci pour ta réponse, ma sa bug toujours :s

voila un extrait de la sortie  le  ~ = /home/tonuser
~/rep_racine/rep3/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././sous_rep3_2_2

sa me fait pareil si je mai le répertoire /home donc je doit dire que j'ai un peux de pain a suivre
samedi 11 avril 2009 à 08:51:13 | Re : récursiviter, lister les répertoires en C++

rt15

Membre Club Administrateur CodeS-SourceS
Hein ???

Eventuellement, il peut y avoir un problème avec une arborescence récursive, c'est à dire un link avec un répertoire parent. Mais ta sortie est bizarre.

Tu as essayé sur une arborescence de répertoires plus simple ?

Au vu de la sortie, peut être que "." et ".." ne sont pas les deux premiers répertoires listés... Essaie de remplacer EnumDirInternal par cette fonction (Non testée) :

/*
 * Utilisée par EnumDir pour pouvoir un premier caractère non const.
 */
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback)
{
  DIR *lpDir;               /* Le répertoire courant      */
  struct dirent *lpChild;   /* Un fils du répertoire      */
  int bContinue;            /* Continuer l'énumération ?  */
   
  bContinue = 1;
  lpDir = opendir(lpDirPath);
 
  /* Si c'est un répertoire */
  if (lpDir)
  {
    /* Appel de la fonction utilisateur */
    if (! lpCallback(lpDirPath))
      bContinue = 0;
    else
    {
      /* Pour tous les fils */
      while (1)
      {
        lpChild = readdir(lpDir);
        if (! lpChild) break;
        if (! strcmp(lpChild->d_name, ".") continue;
        if (! strcmp(lpChild->d_name, "..") continue;

        /* Construction d'un chemin complet vers le fils */
        strcat(lpDirPath, "/");
        strcat(lpDirPath, lpChild->d_name);

        /* Appel récursif */
        if (! EnumDirInternal(lpDirPath, lpCallback))
        {
          bContinue = 0;
          break;
        }
        /* Récupération du parent */
        strrchr(lpDirPath, '/')[0] = '\0';
      }
    }
    closedir(lpDir);
  }
  return bContinue;
}

dimanche 12 avril 2009 à 03:32:21 | Re : récursiviter, lister les répertoires en C++

panthere007

merci pour ta réponse , j'ai pas essayer t'a denière méthode methode, mai je m'en suis inspirer.
le code que je fourni ici fonctionne chez moi, note que le tableau de type vector est facultatif. sinon sa tourne bien.

si tu as une remarque je suis velontaire

code:
#include <iostream>
#include <vector>
#include <string>
#include <dirent.h>
#include <sys/stat.h>
using std::string;

void search_find_file_dir(std::string *,std::vector<string> &done_rep_only);

void search_find_file_dir(std::string *dir_source,std::vector<string> &done_rep_only)
{
    //variable
    DIR *pointeur_flux_dir;
    struct dirent *pointeur_flux_file;
    std:string read_flux_file;
    std::string N="";
    //code
    std::cout << "Le chemin d'acès est: "<< *dir_source << " L'adresse du pointeur est: " << dir_source << std::endl;
    pointeur_flux_dir = opendir((*dir_source).c_str());
    if (pointeur_flux_dir == NULL)
    {
        return;
    }
    while ((pointeur_flux_file = readdir(pointeur_flux_dir)) != NULL)
    {
        read_flux_file = pointeur_flux_file->d_name;
        if ( read_flux_file == "." || read_flux_file == "..")
        {   
            continue;
        }
        if (pointeur_flux_file->d_type == DT_DIR) {
        std::cout << pointeur_flux_file->d_name << std::endl;
        N=*dir_source + "/" + pointeur_flux_file->d_name;
        done_rep_only.push_back(N);
        search_find_file_dir(&N,done_rep_only);
        }
        else
        {
        std::cout << "N'est pas un répertoire: " << pointeur_flux_file->d_name << std::endl;
        }
    }
}
int main()
{
    std::vector<std::string> done_rep_only;
    std::cout << "Démmarage de la recherche des répertoires" << std::endl;
    std::string p;
    p = "/home/taz/rep_racine";
    search_find_file_dir(&p,done_rep_only);
    //affiche le contenu du tableaux
    for (long i = 0; i < done_rep_only.size(); ++i )
    {
        std::cout << done_rep_only[i] << std::endl;
    }
    std::cout << "affichage terminer" << std::endl;
    return 0;
}


Cette discussion est classée dans : rep, search, full, std, transfere


Répondre à ce message

Sujets en rapport avec ce message

algo search_n sur un std::map !!!!!! [ par gege1024 ] je voudrais rechercher le nb d'occurence d'une valeur dans un std::mapje le fait pour un std::vector, c'est tout bon, mais je me demande pourquoi j'ar Aide [ par Hellboy67 ] Voila j'ai un exo pour les cours de prog a faire dont le code source est le suivant:# include # include using std::cout;using std::cin;using std::end Au secour d'un supra débutant !!! [ par Clad49 ] Salut je débute dans le c++ et ma question risque d'étre super conne mais je me lance ;) : void main() int x char rep; cout> rep; if (rep = decouper une chaine de caractere [ par alahyaneali ] Bonjour à tous j'ai cherché partout comment decouper une chaine de caractere en C mais je n y arrive pas. Meme en utilisant substring(date, 1, 2) En f pb dans la conversion d'in int en string!! [ par othland ] j'arrive pas à comprendre!quand je mets :///////////////////////////////////////std::ostringstream oss;oss mon_string = oss.str();//////////////////// compilation .o [ par xantro ] bonjour a tous et a toutes. J'aurai besoin d 'un coup de main pour un probleme de compilation. Voila, j'ai mon programme avec plusieurs fichiers (fic jpeglib.h, g++ & undefined reference [ par MyXiLo ] Bonjour, Je viens de commencer le c++ alors ma question est probablement idiote, cependant je la pose tout de même car elle m'handicap fortement. Mo STL binary search [ par thefakir ] bonsoir, Bonsoir, Voila je suis sur un petit truc de C++ qui calcule une somme avec :cout << std::ac comment distinguer entre fichier et repértoire! [ par almousafer ] salut tlm Je viens d'ecrire une fonction qui parcours le répertoire passé en argument et liste son contenu (merci à Fred), mais il reste encore un pb, comment faire une search bar??? [ par dyn ] bjr,je cherche a developper une barre internet multiplateforme  du type google bar et donc j'aimerais savoir si quelqu'un a des informations sur les t


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 3,635 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales