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

Langage Delphi Discussion :

Valeur retournée par une fonction


Sujet :

Langage 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 Valeur retournée par une fonction
    Bonjour à tous

    Je demande vos lumières pour une erreur incompréhensible que je n'ai jamais rencontrée.

    J'appelle une fonction pour affecter sa valeur à une variable.
    La fonction est dans une unité différente de l'unité où se fait l'appel mais c'est une opétation tout-à-fait courante, non ?
    Or, la valeur de la variable après appel de ma fonction est égale à 0 alors que la fonction renvoie une valeur de 5. J'en ai la certitude après exécution en mode pas à pas.

    Voici le code de l'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Function TStreetForm.NearBtnAction(Parcel : TPolygParams) : Boolean;
    Var
      NoLayer : Integer;
      LayerDirName : String;
    .
    .
    begin
    .
    .
      LayerDirName := TableDbleLieu.FieldValues['DivCode'] + TableDbleLieu.FieldValues['Sect'];
      NoLayer := MapForm.NoLayerFromLayerName(MapForm.Map, LayerDirName + 'CaPa');
    .
    .
    La fonction appelée est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function TMapForm.NoLayerFromLayerName(Map : TMap; LName : String) : Integer;
    Var
      i : Integer;
    begin
      For i := 0 to Map.NumLayers - 1 do
      if Map.LayerName[i] = LName then
      begin
        Result := i;
        Break;
      end;
    end;
    Une idée ?

    Merci d'avance pour vos suggestions.

  2. #2
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut

    Avec un pas-à-pas, dans la fonction NoLayerFromLayerName quelle est la valeur de Map.NumLayers ?

    Si celle-ci est à 0, tu auras bien en retour cette même valeur.

    @+ Claudius

  3. #3
    Aos
    Aos est déconnecté
    Membre habitué

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 189
    Points : 187
    Points
    187
    Par défaut
    Merci d'avance pour vos suggestions.[/QUOTE]

    Perso, j'ai deja eu ce probleme.
    Je l'ai etrangement résolu en faisant un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    NoLayerFromLayerName:=i;
     
    ai lieu de 
     
    result:=i;
    Essaye mais c'est vraiment sans certitude
    c'est censé etre pareil...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Salut,

    Si en remettant Result := i cela fonctionne toujours alors il est probable que Delphi ai "oublié" de recompiler l'unit à un moment, et qu'une modification de code ai entraîner une recompilation (ça m'est déjà arriver ce genre de bugs incompréhensibles qui disparaissent après avoir forcer une recompilation).

  5. #5
    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
    Merci à tous pour vos réponses.

    Ce qui est bizarre c'est qu'en mode pas à pas j'ai une valeur nulle au survol de la souris sur la variable "NoLayer" après exécution de l'instruction d'affectation par la fonction.

    Et quand j'exécute
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ShowMessage(IntToStr(NoLayer));
    , j'ai bien la valeur 5.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 717
    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 717
    Points : 25 613
    Points
    25 613
    Par défaut
    Citation Envoyé par defluc Voir le message
    J'en ai la certitude après exécution en mode pas à pas.
    Justement, tu ne peux pas comme tu viens de le découvrir, il est bien connu qu'en débogage des boucles For, il y a un soucis avec les valeurs qui ne sont pas rétro-optmisé ( une boucle 1 à 10 devient 9 à 0 car c'est plus rapide) ... mieux vaut un ShowMessage bien plus fiable ...



    Sinon, on peut écrire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Function TMapForm.NoLayerFromLayerName(Map : TMap; LName : String) : Integer;
    begin
      For Result := 0 to Map.NumLayers - 1 do
        if Map.LayerName[Result] = LName then
          Exit;
     
      Result := -1;
    end;
    Et cela fonctionne très bien, voir un exemple dans TStrings.IndexOf ...


    Pour les problèmes de compilation partielle bases sur les DCU des PAS non modifié, c'est flagrant sur l'imbrication des sections initializations et l'ordre des uses ... Voir ICI

  7. #7
    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
    J'ai une ancienne version qui n'a pas été modifiée pour ce qui concerne cette instruction et cette fonction qui me renvoie les valeurs attendues.

    Dans ma dernière version bugée, je constate que plus loin dans l'exécution, les valeurs renvoyées par la fonction à nouveau appelée sont encore plus farfelues : 5685729, 1243553, 4266248, ...

    J'ai essayé de modifier la fonction comme proposé par ShaiLeTroll et Aos.

    Même problème.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 834
    Points : 13 587
    Points
    13 587
    Par défaut
    N'aurais-tu pas un With ... do avant spécifiant un objet qui contient aussi une variable NoLayer ?
    Ce serait l'explication d'une valeur différente entre le ShowMessage et le survol de la souris.

  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
    Non Andnotor et NoLayer est une variable locale.

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 717
    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 717
    Points : 25 613
    Points
    25 613
    Par défaut
    les valeurs farfelues, tu as bien mis un Result := -1 à la fin ? attention, c'est un exit qu'il faut utiliser pas un break !

  11. #11
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    supprime tout le fichier garder uniqument ces extentions .dpr .pas .dfm .res il arrive que le compilateur utilise des anciens fichiers compilés essaie aussi d'ajouter le nom de l'unité MapForm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    NoLayer :=Unit1.MapForm.NoLayerFromLayerName(MapForm.Map, LayerDirName + 'CaPa');

  12. #12
    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
    Merci à tous.

    Je dois avancer et j'ai donc repris une ancienne version qui fonctionne en la complétant de mes développements plus récents. Plus de problème.
    Ce qui semble confirmer
    il arrive que le compilateur utilise des anciens fichiers compilés
    .
    Je reviendrai à vous si le problème ressurgit.

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Février 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 141
    Points : 142
    Points
    142
    Par défaut
    Salut,

    Ton bug ressemble fortement à une valeur de retour non initialisée.

    Citation Envoyé par defluc Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function TMapForm.NoLayerFromLayerName(Map : TMap; LName : String) : Integer;
    Var
      i : Integer;
    begin
      For i := 0 to Map.NumLayers - 1 do
      if Map.LayerName[i] = LName then
      begin
        Result := i;
        Break;
      end;
    end;
    Dans cette fonction, si LName n'est pas présent dans la liste de chaînes "Map.Layername", la variable Result n'est jamais initialisée.

    Initialise "Result := -1" avant ta boucle (ou fait comme ShaiLeTroll t'a dit), et vérifie (au debugger) que dans ton parcours de boucle, tu as bien un Layer qui porte le nom LName.

    Note que pour un ordinateur, "5" est tout aussi farfelu que "1243553" ou "5685729". Le fait d'initialiser Result te permettrait de détecter que ton "5" n'est pas le fruit du hasard (ou du fait que ton appli est toujours initialisée de la même façon et que la première valeur qui se trouve sur la pile est "5" la première fois que tu passes dans ce bout de code...)

  14. #14
    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
    Comme je l'ai dit dans mon précédent post,
    Je reviendrai à vous si le problème ressurgit.
    En réponse à ton intervention, j'avais vérifié que LName avait bien une valeur.

    J'ajouterais que le but de ma fonction est de trouver l'indice de LName dans Map.NumLayers, sanchant que la valeur LName y existe toujours.
    ne devrait donc jamais se produire.

  15. #15
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    une dernière suggestion lorsque je ne comprends pas le comportement du l'application je mets des showmessage ou showmessagefmt sur le chemin qu'il doit suivre bien sur qu'il eviter quelque routine boucles ,messages..
    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
    Function TStreetForm.NearBtnAction(Parcel : TPolygParams) : Boolean;
    Var
      NoLayer : Integer;
      LayerDirName : String;
    .
    .
    begin
    .
    .
      showmessage('Phase 1');
      LayerDirName := TableDbleLieu.FieldValues['DivCode'] + TableDbleLieu.FieldValues['Sect'];
      NoLayer := MapForm.NoLayerFromLayerName(MapForm.Map, LayerDirName + 'CaPa');
      showmessagefmt('Phase 3 , NoLayer :%d',[NoLayer]);
    .
    .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Function TMapForm.NoLayerFromLayerName(Map : TMap; LName : String) : Integer;
    Var
      i : Integer;
    begin
      For i := 0 to Map.NumLayers - 1 do
      if Map.LayerName[i] = LName then
      begin
        Result := i;
        Break;
      end;
      showmessagefmt('Phase 2 , Map.NumLayers :%d, Result :%d',[Map.NumLayers,Result]);
    end;
    et comme mes prédécesseurs une fonction doit avoir une valeur de sortie sur touts les statements sauf si tu es bien conscient de ce tu code.
    Function TMapForm.NoLayerFromLayerName(Map : TMap; LName : String) : Integer;
    begin
    For Result := 0 to Map.NumLayers - 1 do
    if Map.LayerName[Result] = LName then
    Exit;

    Result := -1;
    end;
    attention, c'est un exit qu'il faut utiliser pas un break !

  16. #16
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    En réponse à ton intervention, j'avais vérifié que LName avait bien une valeur.
    Ca ne confirme pas que Map contient cette valeur
    essaie de remplacer ta fonction NoLayerFromLayerName par celle ci por afficher le contenu du
    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
    30
    31
    32
    33
    34
    35
    function echo(Map : TMap; LName : String):integer;
    var
    h:TForm;
    m:TListBox;
    i:integer;
    begin
     h:=TForm.Create(nil);
     m:=TListBox.Create(h);
     m.Parent:=h;
     m.Align:=alClient;
     try
             h.Caption:=Format('Recherche :[%s]',[LName]);
       For i := 0 to Map.NumLayers- 1 do
           m.Items.Add(Format('Pos %d ->[%s]',[i,Map.LayerName[i]]));
     
      h.ShowModal;
     finally
      h.Free;
     end;
     result:=0;
    end;
    Function TStreetForm.NearBtnAction(Parcel : TPolygParams) : Boolean;
    Var
      NoLayer : Integer;
      LayerDirName : String;
    .
    .
    begin
    .
    .
     
      echo(MapForm.Map, LayerDirName + 'CaPa');
     
    .
    .
    il peut avoir des erreurs pour ce TMap

Discussions similaires

  1. Réponses: 4
    Dernier message: 30/09/2009, 11h52
  2. [Débutant] Recuperer la valeur retourner par une fonction
    Par chouki dans le forum MATLAB
    Réponses: 1
    Dernier message: 26/05/2009, 10h04
  3. Réponses: 2
    Dernier message: 11/04/2008, 23h58
  4. Réponses: 4
    Dernier message: 07/04/2007, 21h02
  5. valeur retournée par une fonction
    Par Biosox dans le forum C
    Réponses: 13
    Dernier message: 20/01/2007, 00h17

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