[C] parcourir une arborescence de repertoire

parcourir une arborescence de repertoire [C] - C - Programmation

Marsh Posté le 25-02-2006 à 15:37:09    

Bonjour, voila je dispose d'un repertoire MP3 qui contient un repertoire rock et classique. Je voudrais faire un programme en C qui affiche tous les fichiers,répertoires et sous répertoires du repertoire MP3. J'ai réalisé un programme mais le probleme c'est qu'il m'affiche que rock et classique et il n'affiche pas ce qu'il y a dans rock et classique. Pouvez vous m'aider svp.
Voici mon code:
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
 
//Prototypes
DIR *opendir (const char *filename);
struct dirent *readdir (DIR * dirp);
int closedir (DIR * dirp);
 
//ACTION SUR FICHIER ET REPERTOIRE
 
//Action sur un repertoire
void action_dir (const char *dir)
    {printf("%s/\n", dir);}
 
//action sur un rep avt parcour de son contenu
void action_dir_pre (const char *root, const char *dir)
    {printf("\n-> %s/%s/\n", root, dir);}
 
//action sur un re apres parcour de son contenu
void action_dir_post (const char *root, const char *dir)
    {}
 
//action sur un fichier
void action_file (const char *file)
    {printf("%s\n", file);}
 
//DEFINITION D'UNE LISTE CHAINEE SIMPLE
typedef struct slist_t
   {
     char *name;
     int is_dir;
     struct slist_t *next;
   }slist_t;
 
//PARCOURS RECURSIF DES REPERTOIRES
int recursive_dir (char *root, char *MP3)
   {
     slist_t *names = NULL;
     slist_t *sl;
 
     DIR *FD;
     struct dirent *f;
     int cwdlen = 32;
     char *cwd;
     char *new_root;
 
     if (NULL ==(cwd=malloc(cwdlen* sizeof *cwd)))
       {
         fprintf(stderr, "probleme avec malloc\n" );
         exit(EXIT_FAILURE);
       }
 
     //Concatenation new_root="root/MP3"
     if (root)
       {
         int rootlen = strlen (root);
         int dirnamelen = strlen ("MP3" );
         if (NULL == (new_root = malloc((rootlen + dirnamelen +2) * sizeof *new_root)))
           {
             fprintf (stderr, "probleme avec malloc\n" );
             exit (EXIT_FAILURE);
           }
         memcpy (new_root, root, rootlen);
         new_root[rootlen] = '/';
         memcpy (new_root + rootlen + 1, MP3, dirnamelen);
         new_root[rootlen + dirnamelen + 1] = '\0';
       }
     else
         new_root = strdup ("MP3" );
 
     //obtention du repertoire courant
     while (NULL == (cwd = getcwd (cwd, cwdlen)))
        {
          if (ERANGE != errno)
            {
              fprintf (stderr, "probleme avec getcwd (errno= '%s')\n",strerror (errno));
              exit (EXIT_FAILURE);
            }
          cwdlen += 32;
          cwd = realloc (cwd, cwdlen * sizeof *cwd);
        }
     chdir ("MP3" );
 
     //Remplissage de la liste avec les noms des fichiers du rep courant
     if (NULL == (FD = opendir ("." )))
       {
         fprintf (stderr, "opendir() impossible\n" );
         return (-1);
       }
     sl = names;
     while ((f = readdir (FD)))
       {
         struct stat st;
         slist_t *n;
         if (!strcmp (f->d_name, "." ))
             continue;
         if (!strcmp (f->d_name, ".." ))
             continue;
         if (stat (f->d_name, &st))
             continue;
         if (NULL == (n = malloc (sizeof *n)))
            {
              fprintf (stderr, "Plus assez de memoire\n" );
              exit (EXIT_FAILURE);
            }
         n->name = strdup (f->d_name);
         if (S_ISDIR (st.st_mode))
            n->is_dir = 1;
         else
            n->is_dir = 0;
         n->next = NULL;
         if (sl)
           {
             sl->next = n;
             sl = n;
           }
         else
           {
             names = n;
             sl = n;
           }
        }
      closedir (FD);
 
      //parcourt les fichiers et repertoire pour action
      for (sl= names; sl; sl = sl->next)
         {
           if (sl->is_dir)
             action_dir (sl->name);
           else
             action_file (sl->name);
         }
 
      //parcourt les fichiers et rep pr actoin avt traitement recursif et apres traitement recursif
/*      for (sl = names; sl; sl = sl->next)
         {
           if (sl->is_dir)
              {
                action_dir_pre (new_root, sl->name);
                recursive_dir (new_root, sl->name);
                action_dir_post (new_root, sl->name);
              }
         }
*/
      //Nettoyage
      free (new_root);
      while (names)
        {
          slist_t *prev;
          free (names->name);
          prev = names;
          names = names->next;
          free (prev);
        }
      chdir (cwd);
      free (cwd);
      return(0);
   }
 
int main (int argc, char **argv)
    {
     if (argc >= 1)
          recursive_dir (NULL, argv[1]);
      exit (0);
    }

Reply

Marsh Posté le 25-02-2006 à 15:37:09   

Reply

Marsh Posté le 25-02-2006 à 16:55:27    

Bon, je vais être sincère, je n'ai pas envie de tout dérouler l'algo à la main pour voir où est le bug probablement minuscule car apparemment, tout à l'air correct. Evidemment avec la masse de commentaires que tu y as mis, c'est pas non plus très facile de comprendre ce que tu cherches à faire. Mais j'ai quand-même quelques remaques...
 
1) il me semble que ta fonction de traitement reçoit un répertoire en paramètre, se déplace dedans avec "chdir" pour lire son contenu (c'est pas facile de tout comprendre) et génère pour chaque sous répertoire un nom contenant le nom courant concaténé au nom du sous répertoire. A mon avis, si j'ai bien compris ce que tu fais, c'est là qu'est le bug. Si tu as un répertoire "MP3" contenant un sous-répertoire "toto", ben quand tu es dans "MP3" ce que tu vois se nomme "toto" et non "MP3/toto". Donc soit tu ne fais aucun "chdir" (c'est d'ailleurs ce que je te conseillerais car je trouve ce déplacement inutile), soit tu ne concatènes pas le nom du sous-répertoire au nom du répertoire dans lequel tu te trouves.
Donc voici l'algo que je te conseillerais pour ta fonction qui reçoit un répertoire en paramètre

ouvrir répertoire
pour chaque fichier, faire
    si "." ou ".." on saute
    si répertoire, alors
        concaténer nom fichier au nom du répertoire courant
        appeler la fonction pour le nom ainsi créé
    fin  si
    si fichier alors
        afficher le nom
    fin si
fin pour
fermer répertoire


 
2) dans des traitements de chaîne, vaut mieux utiliser "strcpy" et/ou "strcat" (qui gèrent le '\0') plutôt que "memcpy". Et il est plus judicieux d'utiliser "sprintf" pour mettre dans une chaîne plein de trucs plutôt que tous ces "memcpy".
Ainsi, toute cette structure :

 
memcpy (new_root, root, rootlen);  
new_root[rootlen] = '/';  
memcpy (new_root + rootlen + 1, MP3, dirnamelen);  
new_root[rootlen + dirnamelen + 1] = '\0';  

peut être avantageusement remplacé par :

sprintf(new_root, "%s/%s", root, MP3);


 


Message édité par Sve@r le 25-02-2006 à 17:00:54

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed