IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

[C++/POSIX] Fonction récursive pour lister des fichiers


Sujet :

C++

  1. #1
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut [C++/POSIX] Fonction récursive pour lister des fichiers
    Salut tous ,

    je voulais faire une fonction récursive en C++ permettant de lister les fichirs d'un répértoire ainsi que ses sous répértoires , alors j'ai écris ce code C++ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void list_dir( 
      const std::string & n_dossier
    ){
    	struct dirent *a;
    	DIR *dir;
    	dir = opendir(n_dossier.c_str());
    	while ((a = readdir(dir)))
    	{
            std::cout << a->d_name << std::endl;
    		if(!opendir(a->d_name)){
    			std::cout << a->d_name << std::endl;
    		} else {
    			std::cout << "<" << a->d_name << ">" << std::endl;
                            list_dir(a->d_name);
    		}
    	}
    	closedir(dir);
    }
    Mais il ne marche pas , beh il se compile bien mais j'ai un résultat inattendu , parfois ça n'affiche qu'un seul fichier , parfois ça donne plein de points , et parfois ça donne un message d'erreur avec Runtime ...

    Pourriez vous m'aider à résoudre mon probléme ?

    Merci beaucoup d'avance .
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  2. #2
    Membre averti
    Avatar de joellel
    Profil pro
    Inscrit en
    Février 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 234
    Points : 338
    Points
    338
    Par défaut
    Attention, readdir() n'est pas réentrante, tu dois perdre une valeur en cours de route!
    Essaie avec readdir_r() pour voir...

  3. #3
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Salut
    readdir_r n'existe pas .
    Mais j'ai un peu avancé même si ça n'affiche pas toujours l'arborescence compléte...
    Voilà ce que j'ai essayé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <stdio.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <iostream>
    #include "conio.h"
     
    void list_dir( 
      const std::string & n_dossier
    ){
    	struct dirent *a;
    	DIR *dir;
    	dir = opendir(n_dossier.c_str());
    	while ((a = readdir(dir)))
    	{
    		if(!opendir(a->d_name)){
    			std::cout << a->d_name << std::endl;
    		} else {
    			std::cout << "<" << a->d_name << ">" << std::endl;
                list_dir(n_dossier+"/"+a->d_name);
    		}
    	}
    	closedir(dir);
    }
     
    int main(void){
        std::string dossier;
        std::cout << "Dossier : ";
        std::cin >> dossier;
        list_dir(dossier);
        getch();
    }
    S'il vous plait essayez mon code et dites moi ce qui ne va pas avec lui...

    Merci beaucoup beaucoup d'avance .
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    À mon avis, readdir EST PLUS OU MOINS réentrante, du moment qu'on utilise des descripteurs séparés...

    Le problème, c'est que bouazza92 ouvre des descripteurs sans les fermer...
    Et aussi, tu dois peut-être mémoriser les informations de ta dirent autre part avant de rappeler opendir()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Salut ,

    voilà ma fonction fonctionne bien à part quelle produit une boucle infinie si le chemin donné est .. ou . car si c'est un chemin relatif , la liste des chemins contient . et .. et ma fonction récursive les suit à chaque fois car ils sont des repertoires d'aprés le test if(opendir((chemin+a->d_name).c_str())) et biensûr ça ne finira jamais , d'ailleurs je ne comprends pas pourquoi le test if(a->d_name==".." && a->d_name==".") ne fonctionne pas :S , si quelqu'un a une idée sur mon probléme , qu'il m'en fait savoir , voilà mon code source C++ ( non compilable avec un compilateur C ! ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    void list_dir( 
      const std::string & n_dossier
    ){
    	struct dirent *a;
    	DIR *dir;
    	std::string chemin;
    	char chemin_c;
    	chemin=n_dossier;
    	chemin=str_replace("\\","/",chemin);
    	if(chemin.substr(chemin.size()-1,1)!="/") chemin.insert(chemin.size(),"/");
    	dir = opendir(chemin.c_str());
    	while ((a = readdir(dir)))
    	{
            if(a->d_name==".." && a->d_name=="."){} else {
    		if(opendir((chemin+a->d_name).c_str())){
                std::cout << "<" << a->d_name << ">" << std::endl;
                list_dir(chemin+a->d_name);
    		} else {
    		    std::cout << a->d_name << std::endl;
    		}
            }
    	}
    	closedir(dir);
    }
    Merci beaucoup beaucoup d'avance .

    EDIT :

    J'oubliais de poster le code de ma fonction str_replace , le voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    std::string str_replace(
    	std::string motif,
    	std::string remplacement,
    	std::string chaine
    ){
    	std::string sortie;
    	sortie=chaine;
    	for(int i=0;i<chaine.size();i++){
    		if(chaine.substr(i,motif.size())==motif){
    			sortie.erase(i,i+motif.size());
    			sortie.insert(i,remplacement.c_str());
    		}
    	}
    	return(sortie);
    }
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    strcmp() ou une comparaison de strings: Les char* ne sont pas directement comparables...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Sinon , auriez vous une solution pour transformer un chemin relatif en un chemin absolu ?
    Merci d'avance .
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  8. #8
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Citation Envoyé par Médinoc
    strcmp() ou une comparaison de strings: Les char* ne sont pas directement comparables...
    Merci beaucoup pour votre réponse , je vais l'essayer .
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  9. #9
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Merci beaucoup pour votre participation , ma fonction récursive marche très bien maintenant , voici le code pour ceux qui veulent l'utilisation dans leurs codes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <stdio.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <iostream>
    #include "conio.h"
    #include <iostream>
    #include "string.h"
     
    std::string str_replace(
    	std::string motif,
    	std::string remplacement,
    	std::string chaine
    ){
    	std::string sortie;
    	sortie=chaine;
    	for(int i=0;i<chaine.size();i++){
    		if(chaine.substr(i,motif.size())==motif){
    			sortie.erase(i,i+motif.size());
    			sortie.insert(i,remplacement.c_str());
    		}
    	}
    	return(sortie);
    }
     
    void list_dir( 
      const std::string & n_dossier
    ){
    	struct dirent *a;
    	DIR *dir;
    	std::string chemin;
    	char chemin_c;
    	chemin=n_dossier;
    	chemin=str_replace("\\","/",chemin);
    	if(chemin.substr(chemin.size()-1,1)!="/") chemin.insert(chemin.size(),"/");
    	dir = opendir(chemin.c_str());
    	while ((a = readdir(dir)))
    	{
            if(strcmp(a->d_name,"..")==0 || strcmp(a->d_name,".")==0){} else {
    		if(opendir((chemin+a->d_name).c_str())){
                std::cout << "<" << a->d_name << ">" << std::endl;
                list_dir(chemin+a->d_name);
    		} else {
    		    std::cout << a->d_name << std::endl;
    		}
            }
    	}
    	closedir(dir);
    }
     
    int main(void){
        std::string chemin;
    	std::cout << "Le chemin : " ;
    	std::cin >> chemin;
    	list_dir(chemin);
        getch();
    }
    Et merci beaucoup encore .
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

  10. #10
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Ah la la, dire qu'avec Boost.FileSystem, ça prendrait 3 lignes

  11. #11
    Membre régulier
    Inscrit en
    Décembre 2005
    Messages
    225
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 225
    Points : 113
    Points
    113
    Par défaut
    Salut tous ,

    voilà j'ai corrigé un bug avec la fonction str_replace , voici le code source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    std::string str_replace(
    	std::string motif,
    	std::string remplacement,
    	std::string chaine
    ){
    	std::string sortie;
    	sortie=chaine;
    	for(int i=0;i<chaine.size();i++){
    		if(chaine.substr(i,motif.size())==motif){
    			sortie.erase(i,i+motif.size()-2);
    			sortie.insert(i,remplacement.c_str());
    		}
    	}
    	return(sortie);
    }
    Forum Programmation d'OS - Tutoriel pour créer un petit noyau 32 bits .

    ( le développement de littlefoot86 est abandonné ... )

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/02/2009, 09h44
  2. Réponses: 1
    Dernier message: 15/10/2008, 17h56
  3. Fonction récursive pour traitement des fichiers
    Par Montor dans le forum Contribuez
    Réponses: 6
    Dernier message: 29/09/2008, 07h45
  4. [Débutante]requete pour lister des fichiers?
    Par bouba83 dans le forum Access
    Réponses: 8
    Dernier message: 18/05/2006, 16h58
  5. Boucle en Dos pour lister des fichiers selon une date
    Par Corben dans le forum Autres Logiciels
    Réponses: 1
    Dernier message: 17/12/2005, 12h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo