Parcourir une arborescence avec la norme POSIX1, C ANSI

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

Parcourir une arborescence avec la norme POSIX1, C ANSI

par Rockleader » 12 Avr 2014, 19:17

Bonjour, en révisant je me suis rendu compte qu'un corrigé me semblait faux, j'aimerais donc savoir si le code suivant permet bien de parcourir une arborescence.


Code: Tout sélectionner
#define _POSIX_C_SOURCE 1
#include
#include
#include
#include
#include

void parcourirREP(char *nomREP)
{

DIR *rep;
struct dirent* El;
struct stat Infos;

rep=opendir(nomREP);
if(rep==NULL)
{
perror("nomREP : "); /*affichera un message d'erreur spécifique au PATH*/
}
else
{
strcat(nomREP,"/"); /*on concatène un / à la chaine*/
while ((El=readdir(rep)) != NULL)
{
   if (! strcmp(El->d_name,".") && ! strcmp(El->d_name,".."))
   {
      if (stat(nomREP,&Infos)==0)
      {
          if (S_ISDIR(Infos.st_mode)) /* Si c’est un répertoire alors appel récursif*/
          {
              strcat(nomREP,El->d_name);
              parcourirREP(nomREP);
          }
          else /* C’est un fichier */
          {
               strcat(nomREP,El->d_name);
               printf("%s",nomREP);
          }
     }
   }
}
}
}
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Avatar de l’utilisateur
Zorro_X
Membre Naturel
Messages: 77
Enregistré le: 16 Avr 2012, 17:40

par Zorro_X » 13 Avr 2014, 09:44

A la lecture cela semble correct. T'as essayé de le faire compiler pour vérifier les erreurs de syntaxe et/ou de le faire tourner ?
Sinon, je ne vois pas ce qui peut te gêner, la récursivité peut-être ?

Edit : après relecture, le problème réside dans les strcat(...), il y a deux problèmes
1) il faudrait vérifier auparavant que la taille allouée de nomREP permet de contenir la nouvelle chaîne concatenée ;
2) plus important et qui à mon avis devrait faire planter la chose, la chaine nomREP est directement modifiée par les strcat ce qui fait que les résultats vont être foireux dès le 2e tour de boucle ! Il faut créer à chaque fois (avant chaque strcat) une nouvelle chaine qui contiendra la concaténation de nomREP & le repertoire/fichier en cours d'analyse.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 13 Avr 2014, 11:01

Zorro_X a écrit:A la lecture cela semble correct. T'as essayé de le faire compiler pour vérifier les erreurs de syntaxe et/ou de le faire tourner ?
Sinon, je ne vois pas ce qui peut te gêner, la récursivité peut-être ?

Edit : après relecture, le problème réside dans les strcat(...), il y a deux problèmes
1) il faudrait vérifier auparavant que la taille allouée de nomREP permet de contenir la nouvelle chaîne concatenée ;
2) plus important et qui à mon avis devrait faire planter la chose, la chaine nomREP est directement modifiée par les strcat ce qui fait que les résultats vont être foireux dès le 2e tour de boucle ! Il faut créer à chaque fois (avant chaque strcat) une nouvelle chaine qui contiendra la concaténation de nomREP & le repertoire/fichier en cours d'analyse.



Après correction de 2-3 trucs voilà ce que donne le code; pour la longueur de chaines pas de soucis.
Sa compile et s'exécute mais ça ne m'affiche rien ;)

Code: Tout sélectionner

void parcourirREP(char *nomREP)
{

DIR *rep;
struct dirent* El;
struct stat Infos;
char Desi[500];

rep=opendir(nomREP);
if(rep==NULL)
{
printf("Fail\n"); /*affichera un message d'erreur spécifique au PATH*/
}
else
{
strcpy(Desi,nomREP);
strcat(Desi,"/"); /*on concatène un / à la chaine*/
while ((El=readdir(rep)) != NULL)
{
   if (strcmp(El->d_name,".")!=0 && strcmp(El->d_name,"..")!=0)
   {
      if (stat(Desi,&Infos)==0)
      {
          if (S_ISDIR(Infos.st_mode)) /* Si c’est un répertoire alors appel récursif*/
          {
              strcat(Desi,El->d_name);
              parcourirREP(Desi);
          }
          else /* C’est un fichier */
          {
               printf("%s\n",Desi);
          }
     }
   }
}
}
}


int main()
{
char n[100];
strcpy(n,"C-C++");
printf("%s\n",n);
   parcourirREP(n);

return 0;
}



Fail ne s'écrivant pas mon dossier C-C++ est bien ouvert lors du premier appel dans le main.

Or mon dossier C-C++ contient 2 dossier et la chaine semble s'arrêter là puisque rien d'autres ne s'affiche...je comprends pas pourquoi ;)


EDIT: En fait je ne rentre pas dans le while ;)
me serais je trompé sur la condition ?

==> Après vérification oui je dois pas faire while == NULL mais while != NULL :marteau:

Je rentre à présent dans ma boucle, mais rien ne s'affiche !

EDIT2: je ne vois plus vraiment quoi changer au code et à l'exécution ça n'est pas bon du tout x)

Code: Tout sélectionner
C-C++
Fail
C-C++/S4/tp10/rougeNoir.h
C-C++/S4/tp10/rougeNoir.h
C-C++/S4/tp10/rougeNoir.h
Fail
Fail


Dans le dossier tp10 normalement j'ai 4 fichier qui devrait s’afficher or il m'affiche 3 fois le même..
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 16:31

par joel76 » 13 Avr 2014, 15:24

Tu as une belle erreur avec le nom des chaines :
ton code corrige :
Code: Tout sélectionner
void parcourirREP(char *nomREP)
{
    DIR *rep;
    struct dirent* El;
    struct stat Infos;

    rep=opendir(nomREP);
    if(rep==NULL)
    {
        printf("Fail open %s\n", nomREP); /*affichera un message d'erreur spécifique au PATH*/
    }
    else
    {
        while ((El=readdir(rep)) != NULL)
        {
            if (strcmp(El->d_name,".")!=0 && strcmp(El->d_name,"..")!=0)
            {

                char newFile[1024];  // d_name);
                if (stat(newFile,&Infos)==0)
                {
                    if (S_ISDIR(Infos.st_mode)) /* Si c’est un répertoire alors appel récursif*/
                    {
                        printf("On entre dans : %s\n", newFile);
                        parcourirREP(newFile);
                    }
                    else /* C’est un fichier */
                    {
                        printf("Fichier %s\n",newFile);
                    }
                }
            }
        }
        printf("On sort de : %s\n", nomREP);
        closedir(rep);
    }
}

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 13 Avr 2014, 15:41

Super ça marche après modification du \\ en / vu que je suppose que tu es sur windows ;)

J'ai compris l'erreur merci beaucoup !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 16:31

par joel76 » 13 Avr 2014, 15:51

Ca marche aussi avec / sous Windows maintenant (je suis sous Windows 7).C'est l'habitude !

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 13 Avr 2014, 16:00

joel76 a écrit:Ca marche aussi avec / sous Windows maintenant (je suis sous Windows 7).C'est l'habitude !


Alors là tu m'apprends un truc x)

J'ai un windows 8 également et il me met bien les chemins avec des \\

Ou alors il y a une sorte de macro qui saura faire la conversion plus bas ?




Petite question également sans trop de rapport je pense.

Les fonctions que l'on tire des bibliothèques standards du C, stdlib stdio etc etc peuvent s'utiliser sur tous les environnements on est bien d'accord ?

Lorsque je fait un programme en utilisant ma norme POSIX il faudra obligatoirement être sur une distribution UNIX, donc à fortiori du linux ou du mac ? ==> Donc si j'utilise open pour un fichier sur windows il va pas aimer c'est bien ça,, je serais obligé de passer par fopen ?

Et dernière question, stat retourne 0 si on a pu récupérer les infos et que tout c'ets bon bien passé, mais sait on ce qu'il retourne si le résultat plante ? Un nombre précis ou c'est juste tout sauf 0 ?


Bon voilà j'arrête de vous embêter je pense que je devrais pouvoir m'en sortir pendant le partiel de demain ;)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 16:31

par joel76 » 13 Avr 2014, 18:17

Tu peux utiliser open sur un fichier avec Windows. Ton prog je l'ai testé avec Code Blocks puis maintenant avec Visual C, il a simplement fallu que j'installe une api pour pouvoir avoir "dirent.h" (il n'est pas d'origine dans la distribution Visual Studio) et ça roule !
Apparemment, mais je ne veux surtout pas rentrer dans un troll douteux Windows / Linux, Microsoft ne respecte pas complètement la norme Posix, mais je ne programme pas assez système pour le remarquer.

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 17 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite