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

 Delphi Discussion :

Fonction qui ne renvoie rien.


Sujet :

Delphi

  1. #1
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut Fonction qui ne renvoie rien.
    Bonjour,

    J'ai créé une fonction qui me renvoie le nom d'un dossier ou du premier sous-dossier qui contient un fichier de nom donné.
    Cette fonction fonctionne comme je peux le constater grâce à un point de suivi ou l'affichage du résultat par une instruction placée dans la fonction même.

    Cependant, appelée dans une procédure, le résultat de la fonction est une chaîne vide.
    Voici la fonction :
    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
    Function FindFirstDirWithFile(InitRoot, FileName : String) : String;
    var
      FoundResult : TSearchRec;
      Dir: String;
    begin
      Result := '';
      Dir := IncludeTrailingPathDelimiter(InitRoot);
      if FindFirst(Dir + FileName, FaAnyFile, FoundResult)= 0 then
      if (FoundResult.Attr and faDirectory = 0) then
        begin
          Result := Dir;
          SysUtils.FindClose(FoundResult);
    MessageBox(0,PChar(Result),'CadaCom',MB_IconInformation);
          exit;
        end;
      SysUtils.FindClose(FoundResult);
      if FindFirst(Dir + '*', faDirectory, FoundResult)=0 then
        repeat
          if (FoundResult.Attr and faDirectory <>0) and (FoundResult.Name<>'.') and (FoundResult.Name<>'..') then
              FindFirstDirWithFile(Dir + FoundResult.FindData.cFileName, FileName);
        until FindNext(FoundResult) <> 0;
      SysUtils.FindClose(FoundResult);
    end;
    et la procédure appelante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TMainForm.TestClick(Sender: TObject);
    Var
      Msg, OutParcelPath, OutParcel : String;
    begin
      OutParcelPath := 'D:\Cadastre\Matrice2017\';
      OutParcel := 'OUTPUT Parcels_*.xls*';
      msg := FindFirstDirWithFile(OutParcelPath, OutParcel);
      ShowMessage(Msg);
    end;
    D'où peut provenir cette anomalie ?

    Cordialement,

  2. #2
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Distribution

    Informations forums :
    Inscription : Décembre 2003
    Messages : 167
    Points : 209
    Points
    209
    Par défaut
    Bonjour

    vous ne récupérez pas la valeur de l'appel récursif

  3. #3
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Mais j'ai toujours procédé comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      Msg := FindFirstDirWithFile(OutParcelPath, OutParcel);  //  Msg intercepte la valeur de la procédure récursive
      ShowMessage(Msg);

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 633
    Points : 25 340
    Points
    25 340
    Par défaut
    J'ajouterais aussi un Exit pour l'arrêter dès que la fonction a trouvé quelque chose, pour traduire mes propos et ceux de fbalien
    Faut aussi penser au Try Finally

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      if System.SysUtils.FindFirst(..., sr) = 0 then
      begin
        try
          repeat
            I 
          until FindNext(sr) <> 0;
        finally
          System.SysUtils.FindClose(sr);
        end;
      end;
    l'erreur c'est là

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
              Result := FindFirstDirWithFile(Dir + FoundResult.FindData.cFileName, FileName);

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 803
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 803
    Points : 13 485
    Points
    13 485
    Par défaut
    C'est à la ligne 20 qu'il manque un Result :=.
    Et ce n'est pas l'élément du premier sous-répertoire qui sera retourné mais du dernier puisque tu n'interromps jamais la boucle.

  6. #6
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Il y a des choses que je ne comprends pas du point de vue logique.
    C'est bien la valeur affectée à Result avant le exit qui est renvoyée par la fonction et je ne vois donc pas la nécessité de l'instruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
              Result := FindFirstDirWithFile(Dir + FoundResult.Name, FileName);
    Plutôt que simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
              FindFirstDirWithFile(Dir + FoundResult.Name, FileName);
    D'autre part, je constate en exécution pas à pas que le "exit" ne sort pas de la fonction et que le bloc Repeat se poursuit inutilement ce qui peut pénaliser le temps d'exécution si le dossier de départ comporte de nombreux dossiers avec sous-dossiers.
    C'est donc intellectuellement insatisfait que je me contente du code allégé suivant :
    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
    Function FindFirstDirWithFile(InitRoot, FileName : String) : String;
    var
      FoundResult : TSearchRec;
      Dir: String;
    begin
      Result := '';
      Dir := IncludeTrailingPathDelimiter(InitRoot);
      if FindFirst(Dir + FileName, FaAnyFile, FoundResult) = 0 then
      if (FoundResult.Attr and faDirectory = 0) then Result := Dir;
      if FindFirst(Dir + '*', faDirectory, FoundResult) = 0 then
      begin
        Try
          Repeat
          if (FoundResult.Attr and faDirectory <> 0) and
             (FoundResult.Name <> '.') and (FoundResult.Name<>'..') then
              Result := FindFirstDirWithFile(Dir + FoundResult.Name, FileName);
          until FindNext(FoundResult) <> 0;
        Finally
          SysUtils.FindClose(FoundResult);
        end;
      end;
    end;
    En vous remerciant pour votre contribution

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 803
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 803
    Points : 13 485
    Points
    13 485
    Par défaut
    Tu appelles deux fois (ou plus) la même fonction FindFirstDirWithFile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    FindFirstDirWithFile
            ¦
            +-- FindFirstDirWithFile
    Chaque appel a ses propres données sur la pile. La deuxième fonction doit donc retourner son résultat à la précédente.
    Et Exit sort bien de la fonction en cours mais n'a aucune influence sur l'appelante.

    Tu te fais gruger par le debugger qui te montre forcément toujours le même code

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 174
    Points : 41 365
    Points
    41 365
    Billets dans le blog
    63
    Par défaut
    Bonsoir,

    j'aurais plutôt écrit ceci, encore que j'ai un doute
    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
    Function FindFirstDirWithFile(InitRoot, FileName : String) : String;
    var
      FoundResult : TSearchRec;
      Dir: String;
    begin
      Result := '';
      Dir := IncludeTrailingPathDelimiter(InitRoot);
      Try
        if FindFirst(Dir + FileName, FaAnyFile, FoundResult) = 0 then
            if (FoundResult.Attr and faDirectory = 0) then Result := Dir;
         else begin 
     
      if FindFirst(Dir + '*', faDirectory, FoundResult) = 0 then 
      begin
          Repeat
          if (FoundResult.Attr and faDirectory <> 0) and
             (FoundResult.Name <> '.') and (FoundResult.Name<>'..') then
                 
                begin 
                   Result := FindFirstDirWithFile(Dir + FoundResult.Name, FileName);
                   Break;
                 end;  
        until FindNext(FoundResult) <> 0;
        end; 
        Finally
          SysUtils.FindClose(FoundResult);
        end;
    end;

  9. #9
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Je lève le doute, SergioMaster.
    Cela fonctionne.

    Je marque la discussion comme résolue.

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 803
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 803
    Points : 13 485
    Points
    13 485
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    begin 
      Result := FindFirstDirWithFile(Dir + FoundResult.Name, FileName);
     
      if Result <> '' then
        Break;
    end;

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

Discussions similaires

  1. Fonction dans une boucle qui ne renvoie rien
    Par blueice dans le forum Langage
    Réponses: 9
    Dernier message: 16/08/2008, 08h46
  2. Fonction qui ne renvoie rien
    Par grenoult dans le forum VBA Access
    Réponses: 1
    Dernier message: 08/06/2007, 11h15
  3. Requete sql qui ne renvoie rien :-(
    Par patchouli dans le forum Langage SQL
    Réponses: 4
    Dernier message: 06/02/2007, 09h41
  4. Fonction qui ne renvoie rien
    Par philippef dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 14/11/2006, 18h12
  5. [PostgreSql] requête simple qui ne renvoie rien ?
    Par tuxout dans le forum Langage SQL
    Réponses: 6
    Dernier message: 03/08/2006, 14h06

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