![]() |
[C] Parcours récursif des dossiers - Version imprimable +- N-PN White-Hat Project (https://n-pn.fr/forum) +-- Forum : Programmation (https://n-pn.fr/forum/forumdisplay.php?fid=72) +--- Forum : Langages compilés (https://n-pn.fr/forum/forumdisplay.php?fid=25) +--- Sujet : [C] Parcours récursif des dossiers (/showthread.php?tid=2933) |
[C] Parcours récursif des dossiers - InstinctHack - 20-04-2013 io, j'essaye de démarrer en C, mais c'est dur :') Je voudras afficher la totalité de mes fichiers et répertoires et ça à partir de la racine. Le problème c'est que ça compile pas et que j'ignore comment corriger les erreurs. Quelqu'un pour m'aider à avancer ? Code C :
Et voilà le message d'erreurs lors de la compilation : Code BASH :
RE: [C] Parcours récursif des dossiers - Kiwazaru - 20-04-2013 Déjà, je crois qu'on ne peut pas faire : if (opendir(arg) == ENOTDIR) puisque opendir attend de renvoyer quelque chose dans une déclaration DIR* . On devrais donc faire DIR* new; -> new = opendir(new_path); + if ( new != ENOTDIR ).. Ensuite pour l'histoire de récursivité, je pense pas qu'on puisse fonctionner avec une seule fonction, j'avais pensé à deux fonction qui auraient une interaction continuelle entre elles, et ces deux fonctions serait dynamique entre elle aussi, cet à dire qu'elles se complèterait et donc permettrais de parcourir un nouveau dossier sans devoir déclarer une infinité de DIR* ce qui serais totalement bête et de toute façon impossible puisqu'on ne peut prédire le nombre de dossier présent dans un dossier de dossier à l'avance... Pour finir une fonction "int" qui ne renvoi rien ça sert à rien donc fait une fonction "void" :p. Bref on aurais un schéma : int main(); void dParcours(char* path); void dParcours_bis(char *path); Avec dans chacune des fonctions une déclaration de DIR* qui parcourrait le nouveau "path" et qui se renverrais à la fonction dParcours (si la fonction courante est dParcours_bis et vice versa) avec le nouveau dossier trouvé ![]() Je ne sais pas si c'est la solution la plus simple, mais c'est là seule qui m'est venu à l'esprit à la vue de ce post pour éviter une infinité de déclaration DIR* :p Sinon pour l'indentation de ton code, -> if() sans instruction dedans tu peux faire Code C :
if( x == y ){ Ou encore, Code C :
if( x == y ) { } Je sais pas si des compilateurs acceptent Code C :
if( x == y ) RE: [C] Parcours récursif des dossiers - b0fh - 21-04-2013 Plop, opendir() retourne NULL en cas d'erreur. ENOTDIR sera dans errno si il y a lieu. Par contre il n'y a aucun problème pour faire l'affectation directement dans le if, à part peut-être un souci de lisibilité Plutôt que d'avoir une branche if vide, c'est un meilleur style d'inverser la condition. Attention, tu ne peux pas comparer des strings avec == et != en C. Ici j'ai triché comme un porc en me contentant d'ignorer tout ce qui commence par un point. Tu ne peux pas non plus concaténer des strings avec . Il manquait la déclaration de type dans l'argument de ta fonction. Si tu n'utilises pas de prototypes, tu dois déclarer les fonctions avant leur utilisation (donc bouger le main à la fin) Comme ta fonction récursive ne retourne rien, j'ai changé son type de retour en void. J'ai aussi ajouté un return au main. Tu peux aussi utiliser continue pour sauter au début d'une boucle (certains disent que c'est du mauvais style. Je les emmerde.) J'utilise 4096 comme taille maximum pour un path, c'est ce qui est défini dans linux (mais ça n'est pas forcément portable). Plutôt que d'accumuler les allocations mémoire, j'utilise un seul buffer qui contient le chemin complet. La fonction récursive garde deux pointeurs, un vers le début du buffer (qui est utilisée pour le printf du chemin complet), et un vers la fin qui sert a ajouter le / et le nom de la dentry) Je fais le print au début de la fonction récursive, et je ne teste pas si une dentry est un répertoire avant de descendre, parce que si ce n'est pas le cas, le opendir() va rater plus loin (philosophie "let it fail"). Il faut quand même tester si un répertoire est un symlink avant de descendre plus loin, sous peine de se retrouver coincé dans des boucles infinies. Au final ça donne ça: Code : #include <stdio.h> Il y a encore plusieurs améliorations possibles. Par exemple un meilleur traitement d'erreur, l'utilisation de qqch de moins dangereux que strcat(), et surtout un mécanisme d'ouverture du répertoire cible en temps constant (ici, on fait à chaque fois un opendir() sur le path complet, ce qui force le kernel a tout retraverser depuis la racine. Il serait beaucoup mieux de faire des chdir() et de ne faire des opendir() que sur les chemins relatifs trouvés dans les dentry. L'amélioration est laissée comme exercice au lecteur ![]() RE: [C] Parcours récursif des dossiers - Kiwazaru - 21-04-2013 Le problème dans ton code B0fh c'est que ça va opendir(); sur le premier dossier venu et ça ne va pas lister les fichiers qui pourraient être présent à la suite de ce dossier :/ RE: [C] Parcours récursif des dossiers - supersnail - 21-04-2013 @ReVeRse: ben si... si t'arrives à ouvrir le dossier, tu parcours les fichiers, t'appelles la fonction récursive qui va afficher le nom du fichier et retourner à la fonction appelante si c'est pas un dossier (vu que opendir() va fail); la fonction appelante qui va continuer tranquillement à parcourir les fichiers et s'appeler elle-même... RE: [C] Parcours récursif des dossiers - Kiwazaru - 21-04-2013 Le truc là c'est qu'on veut faire par exemple: fichier fichier fichier dossier -> fichier, fichier, dossier, fichier, fichier -> (dans dossier) fichier, fichier fichier On parcourt donc 3 fois la fonction qui va afficher : "Fichier + Fichier + Fichier" et là il va detecter dossier, du coup avec votre code on va rentrer dans dossier qui va nous lister "Fichier + Fichier" qui va detecter le dossier et rentrer dedans et lister "Fichier + Fichier", sauf qu'il aura zappé 3 fichiers, donc il faudra faire une genre de sauvegarde du dossier précédent à chaque dossier parcouru pour aller parcourir la fin de chaque dossier etc... RE: [C] Parcours récursif des dossiers - supersnail - 21-04-2013 Ben c'est le principe de la récursivité ça.... Quand tu sors d'une fonction, tu reviens dans la fonction parente juste après l'appel de la fonction (la magie des stack frames & tout le bordel), so jvois pas pourquoi ça zapperait des fichiers. La récursivité, learn how 2 use it ![]() RE: [C] Parcours récursif des dossiers - Kiwazaru - 21-04-2013 Yep mais là, la fonction qui s'appelle elle même (je savais pas qu'on pouvais faire ça btw :p d'où mes deux fonctions x) ) elle fait toujours la même chose cet à dire check si on a un dossier et si on a un dossier on rentre dedans et on appelle la même fonction et ainsi de suite, je vois pas le moment où on check si il y a d'autre(s) fichier derrière... RE: [C] Parcours récursif des dossiers - supersnail - 21-04-2013 Ben quand tu fais un "return;" ? (ou simplement à la fin de la fonction) Pour simplifier, il se passe ceci: Code : print du dossier1 J'espère que mon schéma pourri t'aidera à mieux comprendre ce qui se passe ![]() RE: [C] Parcours récursif des dossiers - Kiwazaru - 21-04-2013 Ahhh ! Return peut s'utiliser donc comme ça aussi? ![]() Intéréssant ça :> Au temps pour moi je savais pas ![]() RE: [C] Parcours récursif des dossiers - InstinctHack - 21-04-2013 Merci encore bofh pour ton aide ici et sur irc. L'objectif est désormais de ne lister QUE les répertoires et de lancer une fonction à chaque fois : Code : on compte les fichiers qui match à un motif dans ce répertoire voilà le code en php Code PHP :
Si le challenge intéresse quelqu'un de le transcoder en C ![]() RE: [C] Parcours récursif des dossiers - Sh4dows - 22-04-2013 Sinon dans ma présentation il y avait mon myls avec l'option -R (ls -R) ![]() Ce n'était pas une fonction récursive par contre il fonctionnait malgré un code dégueulasse.. https://github.com/Sh4dows/myls/blob/master/main.c <-- fonctions spider RE: [C] Parcours récursif des dossiers - sakiir - 22-04-2013 j'ai deja essayé de faire ca sous Win , et ca été tres difficile .. ^^ Bonne chance |