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 :

Parcours récursif d'une arborescence


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut Parcours récursif d'une arborescence
    Bonjour,

    Je ne suis pas très familier de ce contexte, j'aimerais avoir vos retours sur cette fonction.
    L'objectif est de rechercher la présence d'un fichier f.ext dans un sous-dossier a/b/c et sous-dossiers sans utiliser de bibliothèques tierces avec un code aussi portable que possible (a minima Windows et Linux).
    La fonction retourne 0 si le fichier a été trouvé, une autre valeur selon ce qui a pu se passer.

    path est le répertoire initial,
    name est le fichier recherché
    out sera le chemin complet du fichier, si trouvé

    SIZESIGN est un define, SEP est une macro qui donne le séparateur selon l'OS

    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
    int lib_string_scan_dir_file (char *path, const char *name, char **out)
    {
        DIR *d, *sd;
        struct dirent *entry;
        char dir[SIZESIGN][SIZESIGN];
        char buffer[SIZESIGN];
        int i, k, ndir = 0;
     
        strncpy (dir[ndir++], path, SIZESIGN-1);
        d = opendir (dir[0]);
        if (d == NULL)
            return 1;
     
        while ((entry = readdir (d)))
        {
            if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, "..")))
            {
     
            }
            else
            {
                snprintf (buffer, SIZESIGN-1, "%s%c%s", path, SEP, entry->d_name);
                sd = opendir (buffer);
                if (sd != NULL)
                {
                    k = snprintf (dir[ndir++], SIZESIGN-1, "%s", buffer);
                    if ((k < 0) && (k >= SIZESIGN))
                    {
                        dir[ndir][0] = '\0';
                        ndir--;
                    }
                }
                else
                {
                    if (!strcmp (entry->d_name, name))
                    {
                        k = snprintf (*out, SIZESIGN-1, "%s%c%s", path, SEP, entry->d_name);
                        if ((k < 0) && (k >= SIZESIGN))
                            return 2;
                        else
                            return 0;
                    }
                }
            }
        }
        for (i = 1; i < ndir; i++)
        {
            k = lib_string_scan_dir_file (dir[i], name, out);
            if (k == 0)
                return k;
        }
        return 1;
    }
    Avez-vous des commentaires, des suggestions ?
    Mon code est-il mauvais ou correct ?

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _iri_ Voir le message
    Bonjour,

    Je ne suis pas très familier de ce contexte, j'aimerais avoir vos retours sur cette fonction.
    L'objectif est de rechercher la présence d'un fichier f.ext dans un sous-dossier a/b/c et sous-dossiers sans utiliser de bibliothèques tierces avec un code aussi portable que possible (a minima Windows et Linux).
    La fonction retourne 0 si le fichier a été trouvé, une autre valeur selon ce qui a pu se passer.

    path est le répertoire initial,
    name est le fichier recherché
    out sera le chemin complet du fichier, si trouvé

    SIZESIGN est un define, SEP est une macro qui donne le séparateur selon l'OS

    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
    int lib_string_scan_dir_file (char *path, const char *name, char **out)
    {
        DIR *d, *sd;
        struct dirent *entry;
        char dir[SIZESIGN][SIZESIGN];
        char buffer[SIZESIGN];
        int i, k, ndir = 0;
     
        strncpy (dir[ndir++], path, SIZESIGN-1);
        d = opendir (dir[0]);
        if (d == NULL)
            return 1;
     
        while ((entry = readdir (d)))
        {
            if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, "..")))
            {
     
            }
            else
            {
                snprintf (buffer, SIZESIGN-1, "%s%c%s", path, SEP, entry->d_name);
                sd = opendir (buffer);
                if (sd != NULL)
                {
                    k = snprintf (dir[ndir++], SIZESIGN-1, "%s", buffer);
                    if ((k < 0) && (k >= SIZESIGN))
                    {
                        dir[ndir][0] = '\0';
                        ndir--;
                    }
                }
                else
                {
                    if (!strcmp (entry->d_name, name))
                    {
                        k = snprintf (*out, SIZESIGN-1, "%s%c%s", path, SEP, entry->d_name);
                        if ((k < 0) && (k >= SIZESIGN))
                            return 2;
                        else
                            return 0;
                    }
                }
            }
        }
        for (i = 1; i < ndir; i++)
        {
            k = lib_string_scan_dir_file (dir[i], name, out);
            if (k == 0)
                return k;
        }
        return 1;
    }
    Avez-vous des commentaires, des suggestions ?
    Mon code est-il mauvais ou correct ?
    Salut
    J'ai des commentaires
    1) Que fait ton code quand d_name vaut "." ou ".." ? Tu as mis un if mais vide
    2) je ne comprends pas le if ((k < 0) && (k > SIZESIGN)). Une variable peut-elle être à la fois plus petite que 0 et plus grande qu'un entier positif ?
    3) A quoi te sert la variable k dans le dernier for ?
    4) ton code ne gère pas les liens symboliques (boucle infinie possible)

    J'ai aussi des suggestions : Tu peux simplifier if (machin) return 2 else return 0 par return machin ?2 :0
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Salut
    J'ai des commentaires
    1) Que fait ton code quand d_name vaut "." ou ".." ? Tu as mis un if mais vide
    2) je ne comprends pas le if ((k < 0) && (k > SIZESIGN)). Une variable peut-elle être à la fois plus petite que 0 et plus grande qu'un entier positif ?
    3) A quoi te sert la variable k dans le dernier for ?
    4) ton code ne gère pas les liens symboliques (boucle infinie possible)

    J'ai aussi des suggestions : Tu peux simplifier if (machin) return 2 else return 0 par return machin ?2 :0
    1/ Rien
    J'ai laissé pour une possibilité d'action ultérieure.

    2/ Boulette et grand merci ! Et comme j'ai bêtement recopié le premier pour le second ...
    Il s'agit d'un || et non d'un &&
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if ((k < 0) || (k > SIZESIGN))
    /* erreur */
    3/ Le k est le retour du scan du sous-dossier en cours. S'il vaut 0, c.à.d. le fichier a été trouvé, on sort de la fonction courante et, par ricochet, des fonctions récursives supérieurs.
    Impropre ? Non fiable ?

    4/ Les liens symboliques. Effectivement ... Comment faire ?
    Sans passer par des API spécifiques. As-tu une piste, une idée ?

    Suggestion : merci, j'avais des printf de retour au milieu mais le code sera bien plus lisble sans cette lourdeur.

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _iri_ Voir le message
    3/ Le k est le retour du scan du sous-dossier en cours. S'il vaut 0, c.à.d. le fichier a été trouvé, on sort de la fonction courante et, par ricochet, des fonctions récursives supérieurs.
    Impropre ? Non fiable ?
    Inutile
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    if (lib_string_scan_dir_file (dir[i], name, out) == 0) return 0:

    Citation Envoyé par _iri_ Voir le message
    4/ Les liens symboliques. Effectivement ... Comment faire ?
    Sans passer par des API spécifiques. As-tu une piste, une idée ?
    Utiliser stat() sur le répertoire supposé. Cette fonction te remplit une structure (que tu auras déclarée) avec les caractéristiques du fichier. Ensuite te suffit de vérifier le champ st_mode de cette structure. Et comme c'est un champ mélangeant plusieurs infos (type et droit), il y a des macros toutes faites pour extraire l'info comme S_IFDIR() et S_IFLNK()

    Citation Envoyé par _iri_ Voir le message
    Suggestion : merci, j'avais des printf de retour au milieu mais le code sera bien plus lisble sans cette lourdeur.
    C'est pratique pour vérifier...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Inutile
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    if (lib_string_scan_dir_file (dir[i], name, out) == 0) return 0:
    C'est exact, la même chose en plus condensé.
    C'était dans le cas ultérieur où la possibilité de retourner tous les fichiers satisfaisant à la demande. Mais même dans ce cas, c'était inutile.

    Citation Envoyé par Sve@r Voir le message
    Utiliser stat() sur le répertoire supposé. Cette fonction te remplit une structure (que tu auras déclarée) avec les caractéristiques du fichier. Ensuite te suffit de vérifier le champ st_mode de cette structure. Et comme c'est un champ mélangeant plusieurs infos (type et droit), il y a des macros toutes faites pour extraire l'info comme S_IFDIR() et S_IFLNK()
    Je n'ai jamais eu de problème avec stat() sous Linux mais sous Windows, tout n'est pas implémenté (en tout cas dans les header fournis avec MingW). Je testerai.

    Citation Envoyé par Sve@r Voir le message
    C'est pratique pour vérifier...
    C'est le but

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _iri_ Voir le message
    Je n'ai jamais eu de problème avec stat() sous Linux mais sous Windows, tout n'est pas implémenté (en tout cas dans les header fournis avec MingW). Je testerai.
    Le pb c'est que tu veux un outil utilisable sous Linux et sous Windows. Donc même si Windows ne sait pas ce qu'est un lien symbolique, il te faut gérer ça dans le cas où ton pg sera exécuté dans Linux.

    Et en réfléchissant un peu plus à cette problématique, on en arrive à la conclusion que tu risques de devoir passer par de la compilation conditionnelle style
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #if TARGET=LINUX
        ... (le code qui gère la particularité Linux)...
    #elif TARGET=ZINDOW
        ... (le code qui gère la particularité Windows)...
    #else
        ... (le code qui gère la particularité de cet OS particulier)...
    #endif
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Parcours récursif d'une arborescence
    Par Michel Deriaz dans le forum Codes sources à télécharger
    Réponses: 1
    Dernier message: 13/09/2017, 17h30
  2. [XSLT] Parcours récursif d'une liste
    Par Tueur_a_gage dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 15/06/2007, 14h05
  3. Parcours en largeur d'une arborescence->Vector
    Par Paniez dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 07/12/2006, 22h21
  4. [VBA-A]Parcours d'une arborescence dossiers et fichiers
    Par sidneyvba dans le forum VBA Access
    Réponses: 2
    Dernier message: 20/03/2006, 16h58
  5. Parcours très rapide d'une arborescence ?
    Par Invité dans le forum C++Builder
    Réponses: 7
    Dernier message: 06/05/2005, 09h24

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