Capturer l'arborescence des dossiers par récursivité indirecte

Soyez le premier à donner votre avis sur cette source.

Vue 7 756 fois - Téléchargée 454 fois

Description

Vous connaissiez la récurrence sans récursivité ? Démonstration... Astucieuse et performante. Le but recherché par ce code est d'accroître l'optimisation de la mémoire RAM. En effet, l'auto-récurrence directe consomme beaucoup de mémoire, car les procédures s'enchaînent alors qu'elles ne sont pas encore terminées. Ici, il n'y a rien de tout ça, car le code utilise un couple de procédures qui exploitent la même variable et qui s'informent l'une l'autre (version 1 seulement).

Posons:
(1) la procédure principale
(2) la fonction assistante qui dresse la liste des sous-dossiers en fonction des paramètres donnés par /1/.

Expliquons le principe en prenant un exemple. Imaginons l'arborescence suivante ordonnée. On suppose aussi que la fonction FindNext renvoit les fichiers par ordre alphabétique:
c:\
c:\Alphonse\
c:\Alphonse\Buffle\
c:\Alphonse\Girafe\
c:\Barbara\
c:\Barbara\Citroën\
c:\Barbara\Lada\
c:\Barbara\Lada\Airbag\
c:\Barbara\Lada\ESP de série\
c:\Barbara\Porsche\
c:\Chantal\

>>>====================>>>
>>> PREMIERE IDEE IMPLEMENTEE LE 08/12/04 <<<

La procédure (1) initialise la liste DIRSTL sur "c:\" (niveau 0). La fonction (2) énumère alors les sous-dossiers en ajoutant les résulats à DIRSTL. Mais (1) ne le sait pas. En revanche, ce qu'elle sait, c'est si oui ou non des dossiers ont été ajoutés. Si c'est le cas, elle se branche sur le premier dossier ajouté par (2) et considère les dossiers suivants qui ont donc été ajoutés par (2). On refait de même: sur ordre de (1), (2) dresse la liste les dossiers, et (1) les prend en compte et fait ensuite lister (2)...

Ainsi, le résultat avant le tri est ainsi:
### ETAPE 0 ###
c:\
### ETAPE 1 ###
c:\Alphonse\
c:\Barbara\
c:\Chantal\
### ETAPE 2 ###
c:\Alphonse\Buffle\
c:\Alphonse\Girafe\
c:\Barbara\Citroën\
c:\Barbara\Lada\
c:\Barbara\Porsche\
### ETAPE 3 ###
c:\Barbara\Lada\Airbag\
c:\Barbara\Lada\ESP de série\

On voit ainsi qu'à chaque fois que (1) fait lister (2), on passe à un niveau de sous-dossier supérieur. C'est une récurrence sans récursivité. C'est ce que j'appelle de la récursivité indirecte.

>>>====================>>>
>>> SECONDE IDEE IMPLEMENTEE LE 18/12/04 <<<

En fait, l'idée pourrait être bien meilleure. En effet, pourquoi ajouter les sous-dossiers à la fin de la liste, et non pas juste en-dessous de l'item actuellement scanné ? Cela permettrait d'avoir un scan plus logique. Si on reprend l'arborescence précédente, compte tenu du nouveau programme, on obtient ceci :

c:\
c:\Alphonse\
c:\Alphonse\Girafe\
c:\Alphonse\Buffle\
c:\Barbara\
c:\Barbara\Porsche\
c:\Barbara\Lada\
c:\Barbara\Lada\ESP de série\
c:\Barbara\Lada\Airbag\
c:\Barbara\Citroën\
c:\Chantal\

La logique de cette liste peut être déroutante, mais remarquez simplement qu'il y a de nombreuses inversions liées à l'utilisation de la fonction Insert. Le désordre règne finalement, mais on s'en fiche pas mal, car les fonctions FindNext et compagnie prennent en réalité le fichier qui tombe sous la main quelque soit son classement alphabétique par rapport aux autres fichiers du même répertoire. Ainsi, pour que tout soit très beau, on a quand même besoin d'utiliser la fonction ~.Sort dans n'importe quelle idée. C'est juste que le classement sera légèrement plus rapide si les items sont déjà un peu classés.

Source / Exemple :


program RecDir;
uses Windows, Classes, SysUtils, Dialogs;
var DirSTL : TStringList;

  function IncludeTrailing(const S: string): string;
  begin
    Result:=S;
    if not IsPathDelimiter(Result,Length(Result)) then
      Result:=Result+'\';
  end;

  function IsDirectory(SRec:TSearchRec):boolean;
  begin
    IsDirectory:= SRec.Attr and faDirectory <> 0;
  end;

procedure AddSubDirs(Dir,Mask:string;Index:integer);
var AttrWord     : integer;
    Pntr, s1, s2 : string;
    Recherche    : TSearchRec;
begin
  AttrWord:=faDirectory or faReadOnly or faArchive or faHidden or faSysFile;
{$I-} ChDir(Dir); {$I+}
  while Mask<>'' do
    begin
      if Pos(';',Mask)=0 then Pntr:=Mask
      else Pntr:=Copy(Mask,1,Pos(';',Mask)-1);
      if FindFirst(IncludeTrailing(Dir)+Pntr, AttrWord, Recherche)=0 then
        begin
          repeat
            s1:=ExtractFileName(Recherche.Name);
            s2:=IncludeTrailing(Dir+s1);
            if (s1<>'.') and (s1<>'..') and (IsDirectory(Recherche)) then
              DirSTL.Insert(Index+1, UpperCase(s2));
          until FindNext(Recherche)<>0;  
          SysUtils.FindClose(Recherche); 
        end;
      if Pos(';',Mask)=0 then Break
      else Mask:=Copy(Mask,Pos(';',Mask)+1,Length(Mask));
    end;
end;

procedure RecurseSubFolder(Rcn:string);
var Idx : integer;
begin
  Rcn:=IncludeTrailing(Rcn); 
  DirSTL.Clear; 
  DirSTL.Add(UpperCase(Rcn)); 
  Idx:=0; 
  repeat
    AddSubDirs(DirSTL[Idx],'*.*',Idx); 
    Idx:=Idx+1; 
  until (Idx>=DirSTL.Count); 
  DirSTL.Sort; 
end;

begin
  DirSTL:=TStringList.Create;
  RecurseSubFolder('c:\mes documents\');
  ShowMessage(DirSTL.Text);
  DirSTL.Clear;
  DirSTL.Free;
end.

Conclusion :


Le code source tient uniquement dans un fichier DPR. Aucun PAS ni DFM... De plus, le Zip est annoté.

Vous pouvez toujours aller voir http://altert.family.free.fr/

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

ni69
Messages postés
1529
Date d'inscription
samedi 12 juin 2004
Statut
Membre
Dernière intervention
5 juillet 2010
6 -
Mais grandvizir à Delphi3 ;)
hoby500
Messages postés
87
Date d'inscription
mardi 25 février 2003
Statut
Membre
Dernière intervention
26 mai 2019
-
la routine :
function IncludeTrailing(const S: string): string;

existe déjà dans Delphi depuis le 5.0 au moins :
et elle se nommme :

function IncludeTrailingBackSlash(const S: string): string;
et il y a aussi
function ExcludeTrailingBackSlash(const S: string): string;
pour faire l'inverse
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
8 -
Je crois que ça va être difficile de raccourcir encore. J'ai déjà épuisé toutes mes idées... mais si une me venait à l'esprit, alors je n'hésiterais pas à poster une idée N°3, sans les caractères spéciaux dans le nom des dossiers bien sur.

Merci de ton soutien fort sympathique. 8-))
JulioDelphi
Messages postés
2349
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
11 -
merciiiiiiii
bon c bien mieux cette idee n°2, ce que je fais en 3300ms tu le fais en 3800ms !
ça c de l'optimisation :)
tu crois ke tu peux encore reduire ? c deja pas mal !
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
8 -
Je suppose que c'est à cause de ton avantage de membre club avec le lien Télécharger. Ok, je te la remet tout de suite...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.