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

Lazarus Pascal Discussion :

[2.2.6] Problème de passage de données dans une fonction [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 103
    Points : 1 065
    Points
    1 065
    Par défaut [2.2.6] Problème de passage de données dans une fonction
    Bonjour à toutes et à tous,

    Le problème que je rencontre n'existait pas alors que j'utilisais des versions précédentes de Lazarus. Je viens encore de le vérifier avec la version 1.6.4. Je n'ai plus la version 2.1.2 avec laquelle, il me semble que ça fonctionnait toujours. Aujourd’hui, avec la version 2.2.6 : ça bugue !

    La procédure en question est la suivante :

    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
    36
    37
    38
    39
    40
    function StringToDate(Dt, Frmt: string): TDateTime;
    {Transforme une chaîne représentant une date en date au format TDateTime. La
     chaîne "Frmt" représente le format de la date "Dt". "Frmt" doit comporter
     le même nombre de caractères que "Dt". Le caractère "D" est mis là où sont les
     caractères (2) représentant le jour, le caractère "M" est mis là où sont les
     caractères (2) représentant le mois et le caractère "Y" est mis là où sont les
     caractères (2 ou 4) représentant l'année. Tout autre caractère est mis en lieu
     et place des caractères de séparation, s'il y en a. Exemples :
      - 08/06/11 --> DD/MM/YY ou DD-MM-YY ou DDxMMyYY
      - 20110608 --> YYYYMMDD}
    var
      CY, i, MY, Y: Integer;
      SY, SM, SD: string;
    begin
      SY:= '';
      SM:= '';
      SD:= '';
      for i:= 1 to Length(Frmt) do
      begin
        if Frmt[i] = 'Y' then
          SY:= SY+Dt[i]                        {Repérage des caractères de l'année}
        else
          if Frmt[i] = 'M' then
            SM:= SM+Dt[i]                         {Repérage des caractères du mois}
          else
            if Frmt[i] = 'D' then
              SD:= SD+Dt[i];                      {Repérage des caractères du jour}
      end;
      Y:= StrToInt(SY);
      if (Y < 100) then                {Si l'année est codée sur deux chiffres ...}
      begin
        MY:= (CurrentYear div 100)*100;
        CY:= CurrentYear-MY;  {.. et que cette valeur est > à l'année courante, ..}
        if (Y > CY) then
          Y:= Y+MY-100                    {... on se place au siècle précédent ...}
        else
          Y:= Y+MY;                     {sinon, on se place dans le siècle courant}
      end;
      Result:= EncodeDate(Y, StrToInt(SM), StrToInt(SD));
    end;
    et elle bugue lors de l'appel suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        DateTimeToString(S, FormatDateN, StringToDate(S, DateSep));{Remise au format dd/mm/yyyy}
    C'est-à-dire lorsqu'elle est un paramètre passé à la fonction "DateTimeToString".

    A d'autres endroits de mon programme où j'utilise "StringToDate" directement, ça se passe bien.

    Le problème, que je détecte en passant la souris sur une variable, est le suivant :

    • Dans "DateTimeToString", "S vaut : "22/02/2024",
    • Je fais F7 pour entrer dans "StringToDate" et "Dt" vaut : "22/02/24;219.00;222.50;218.70;221.50;551476"
    • J'avance d'un pas (F7) et "Dt" passe à "nil" et donc logiquement la suite bugue.


    Je ne comprends pas ce qui se passe. J'ai nettoyé et reconstruit le programme, j'ai essayé différents niveaux d'optimisation (0, 1, 2), le problème est le même.

    Par ailleurs, même quand ça fonctionne, les infos du débogueur me laissent rêveur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Result = 20/03/2014
    var
     Result: TDateTime
    E:\Lazarus\Projets_ChP\Gestion_Valeurs\GesUtils.pas(571,42)
    Result = 20/03/2014 alors que result est du type TDateTime !!

    Si vous avez une idée du problème ...

    Cordialement.

    Pierre.

  2. #2
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 487
    Points : 4 718
    Points
    4 718
    Par défaut
    Bonjour,

    Cela ressemble beaucoup à un string qui peut désigner une chaîne courte ou une chaîne sans limite AnsiString selon les flags $H et les versions qui ont un mode par défaut. Historiquement (Turbo Pascal) seule la chaîne courte existait, puis les chaînes AnsiString sont apparues mais n'ont pas détrôné de suite l'ancêtre, mais tout a une fin.

    Les 256 caractères initiaux pouvaient passer en argument par valeur mais c'est un peu plus difficile avec des chaînes potentiellement illimitées.

    Essayer de remplacer string il y a shortstring ou (mais c'est laid) mettre des var ?

    Par ailleurs, la fonction peut être simplifiée (même si je reste perplexe sur son aptitude surprenante à traiter "YYDMDMYY" ).

    Code Pascal : 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
    function StringToDate(Dt, Frmt: string): TDateTime;
    var
      i, u, D, M, Y : Integer;
    begin
       Y := 0;     M := 0;     D := 0;
       for i:= 1 to Length(Frmt) do begin
          u := Ord(Dt[i]) - Ord('0');
          case Frmt[i] of
             'D': Y := Y * 10 + u;
             'M': M := M * 10 + u;
             'Y': Y := Y * 10 + u;
          end;
       end;
       if Y < 100 then begin                         // Si l'année est codée sur deux chiffres ...
          u := CurrentYear mod 100;                  // Quantième
          if u < Y then Y += CurrentYear - u - 100 else Y += CurrentYear - u;
       end;
       Result:= EncodeDate(Y, M, D);
    end;

    Salutations

  3. #3
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 103
    Points : 1 065
    Points
    1 065
    Par défaut
    Merci Guesset pour ces explications et ces propositions. Je n'ai pas essayé "var" mais "shortString". Ça ne fonctionne pas. Je pense que le problème vient du fait que dans une même instruction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DateTimeToString(S, FormatDateN, StringToDate(S, DateSep));{Remise au format dd/mm/yyyy}(S, FormatDateN, StringToDate(S, DateSep));{Remise au format dd/mm/yyyy}
    S doit être passé par adresse dans "DateTimeToString" et par valeur dans "StringToDate". Ce qui doit laisser perplexe le compilateur qui doit faire un choix.

    J'ai résolu le problème en utilisant une variable intermédiaire "STD" du type TDateTime comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        STD:= StringToDate(S, DateSep);
        DateTimeToString(S, FormatDateN, STD);{Remise au format dd/mm/yyyy}
    Le problème vient donc bien d'une évolution de la prise en compte du String dans la nouvelle version de Lazarus qui, de fait, n'assure plus de compatibilité ascendante.

    Pa ailleurs, j'ai toujours le problème de type de variable montré par le débogueur.

    Cordialement.

    Pierre.

  4. #4
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 487
    Points : 4 718
    Points
    4 718
    Par défaut
    Bonjour,

    Si la fonction DateTimeToString(S, strFormat, DT) s'attend un troisième argument passé par référence (var...), le retour d'une fonction ne peut fonctionner car c'est une valeur éphémère sans adresse accessible (souvent un simple registre).

    Je n'ai pas vérifié mais la fonction a peut être évolué, même si c'est une peu bizarre car un DateTime ne prend "que" 64 bits tout comme son adresse (en mode 64 bits bien sûr), il n'y a donc ni gain en place ni en efficacité (plutôt moins bonne car il y a une indirection).

    Auquel cas il reste ta solution d'une variable intermédiaire qui pérennise le retour de la fonction dans un espace qui a une adresse.

    Salutations

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

Discussions similaires

  1. passage pointeur NULL dans une fonction
    Par reptils dans le forum C
    Réponses: 4
    Dernier message: 12/05/2006, 00h12
  2. Réponses: 3
    Dernier message: 20/03/2006, 18h46
  3. Réponses: 9
    Dernier message: 13/05/2005, 04h13
  4. Réponses: 6
    Dernier message: 24/12/2004, 17h46
  5. [langage] Passage de paramètres dans une fonction
    Par And_the_problem_is dans le forum Langage
    Réponses: 11
    Dernier message: 28/06/2004, 09h20

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