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 :

Problème de Pointer dans TList [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut Problème de Pointer dans TList
    Bonjour,

    Je réfléchis à la possibilité de gérer des données par l'intermédiaire d'un TList qui manipule des pointeurs...
    Je me heurte à un problème d'affectation d'un pointeur dans une procédure.
    J'ai créé une Liste d'Objets Céleste dont voici le code.
    Précision : je suis parti d'un exemple que j'avais en Delphi, j'ai converti le projet avec le menu Outils|Conversion Delphi|Convertir un projet Delphi en projet Lazarus. J'ai donc la directive de compilation suivante en début de chaque unité : {$MODE Delphi} ! Mais je ne pense pas que cela change quelque chose pour mon problème!


    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    Type
      {Champ des données du Catalogue des étoiles}
    
      PListeObjets = ^TObjetsCelestes;
      TObjetsCelestes =
        Record
          elNom   :String[22];
          elCooGalX : Integer;
          elCooGalY : Integer;
          elCooGalZ : Integer;
        End; 
    
    ...
    
    var
      Form1 : TForm1;
      Liste : TList;
    
    implementation
      uses Unit2;
      {$R *.lfm}
    {==============================================================================}
    
    {--- Initialisation du catalogue ------------------}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Liste := TList.Create; // Création de la liste
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Form1.btnToutSupprimerClick(nil);
      Liste.Free;
    end;
    
    {--- Transfert les Saisies de la Fiche Form2 vers le Buffer des Objets de la Liste
    -------------------------------------------------------------------------------}
    procedure TForm1.SaisieFicheToRecord(aObjet : PListeObjets);
    begin
      With aObjet^ Do With Form2 do
      begin
        elNom     := edNom.Text;
        elCooGalX := edX.Value;
        elCooGalY := edY.Value;
        elCooGalZ := edZ.Value;
      end;
    end;
    
    {--- Affichage des Objets Célestes du Catalogue dans une ListBox --------------}
    Procedure TForm1.MAJAfficheListe;
      Var i:Integer;
    Begin
      ListBox1.Items.Clear;
      With Liste Do For i:=0 To Count-1 Do
        if Items[i] = nil
           then ListBox1.Items.Add('< liste vide >')
           else With TObjetsCelestes(Items[i]^)
                 Do ListBox1.Items.Add(Format('%-20s%5d%5d%5d',[elNom,elCooGalX,elCooGalY,elCooGalZ]));
      lbNombre.Caption := IntToStr(Liste.Count);
    End;
    
    {--- Ajoute un Objet Céleste ---------------------------------------------------
    -------------------------------------------------------------------------------}
    procedure TForm1.btnAjouterClick(Sender: TObject);
     Var Objet : PListeObjets;
    begin
      {Valeurs par défaut}
      With Form2 do
      begin
        edNom.Text := 'Nouveau Objet Céleste';
        edX.Value  := 100;
        edY.Value  := -200;
        edZ.Value  := 300;
      end;
    
      {Affichage saisie nouveau Objet Céleste: étoile, galaxie, planète...}
      if Form2.ShowModal <> mrOK then Exit;
    
      {Création nouveau objet céleste dans Liste}
      New(Objet);
      SaisieFicheToRecord(Objet);
      Liste.Add(Objet);
    
      {Mise a jour Affichage}
      MAJAfficheListe;
    end;
    
    {--- Modifie un Objet Céleste --------------------------------------------------
    -------------------------------------------------------------------------------}
    procedure TForm1.btnModifierClick(Sender: TObject);
     var Objet : PListeObjets;
    begin
      if ListBox1.ItemIndex < 0 then Exit;
    
      {Test si l'objet Céleste n'est pas vide (nil) }
      if Liste.Items[ListBox1.ItemIndex] = nil then Exit;
    
      {Affichage de ses données et valeurs}
      With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^) Do
      With Form2 do
      begin
        edNom.Text := elNom;
        edX.Value  := elCooGalX;
        edY.Value  := elCooGalY;
        edZ.Value  := elCooGalZ;
      end;
     
      {Demande de modification de l'objet Céleste}
      if Form2.ShowModal <> mrOK then Exit;
    
      {Mise à jour des valeurs}
      With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^) Do SaisieFicheToRecord(Objet);
    { With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^)Do
      With Form2 do
      Begin
        elNom    := edNom.Text;
        elCooGalX   := edX.Value;
        elCooGalY      := edY.Value;
        elCooGalZ      := edZ.Value;
      End;
    }
    
      {Mise a jour Affichage dans LisBox}
      MAJAfficheListe;
    end;
    Unit2 est juste une fiche modale ne comprenant aucune ligne de code pour la saisie des données :

    Nom : Aide15.jpg
Affichages : 141
Taille : 23,8 Ko

    La liste se crée et s'affiche correctement dans la ListBox.
    Le problème se trouve quand je veux modifier une valeur dans un Objet choisi dans la ListBox.
    L'instruction en rouge Plante car Objet n'est pas affecté du Pointeur qui est en relation avec l'affichage des valeurs de l'Objet que l'on veut afficher.
    Si je remplace l'instruction SaisieFicheToRecord(Objet); par son équivalent en Vert, ça marche. Cela confirme que Objet passé en paramètre n'est pas initialisé, mais je n'arrive pas à le faire...

    Je tourne en rond et ne parviens pas à trouver la méthode pour affecter la valeur du pointeur de l'objet affiché !
    Est-ce que quelqu'un a une idée ?
    Je posterais ensuite le code dans son ensemble car j'ai testé d'autres possibilités qui fonctionnent.
    Merci

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 087
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 087
    Points : 15 506
    Points
    15 506
    Billets dans le blog
    9
    Par défaut
    Bonjour !

    Il me semble que la ligne suivante devrait faire l'affaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Objet := Liste.Items[ListBox1.ItemIndex];
    SaisieFicheToRecord(Objet);

  3. #3
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Il me semble que la ligne suivante devrait faire l'affaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Objet := Liste.Items[ListBox1.ItemIndex];
    SaisieFicheToRecord(Objet);

    Merci Roland,

    Cependant les modifications n'apparaissent pas correctement...
    Je vais refaire des essais. J'ai constaté que le premier élément de la listBox a un itemindex = 1, alors que j'étais habitué à un itemIndex = 0 sur le premier élément...
    Il semble que je vais devoir écrire des lignes de codes dans Form2 pour mettre à jour correctement l'affichage dans la listBox de Form1...
    A+

  4. #4
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut Source test
    Bonjour,

    Je mets en pièce jointe un extrait du source du projet.
    J'ai supprimé des fonctions qui fonctionnent et ne posent pas de problème...
    J'ai refais l'exemple ci-joint le dans le Pur Lazarus => Dispose qui était accepté dans le mode Delphi est remplacé par FreeMem

    Résultat exécution:
    J'ai toujours le problème d'actualisation de l'Affichage qui vient de l'actualisation des pointeurs lorsque je cherche à modifier un Objet de la Liste par un clic sur la ListBox...
    Exemple:
    Nom : Aide19.jpg
Affichages : 109
Taille : 78,9 Ko

    Voilà, en 2, lors du clic sur Objet Céleste, on remarque que ce sont les données du dernier objet saisi qui apparaissent. Le changement de valeurs des index ne semble pas la bonne piste...

    Si vous avez une idée?
    Je vais peut être faire un Test sur la gestion à partir de Form2!
    Ci joint, le fichier test : project1.zip
    A+

  5. #5
    Invité
    Invité(e)
    Par défaut
    Supprime le code de l’événement Listbox1OnClick il est incorrecte

    Le problème est que les champs de Form2 ne sont pas initialisés par les données de l'enregistrement à modifier et gardent les anciennes valeurs saisies

    dans le code de modifications ajouter :

    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
      {Affichage de ses données et valeurs}
      //showmessage('Index iLB/iTot = '+inttostr(iLB)+' / '+inttostr(Listbox1.Count));
      With TObjetsCelestes(Liste.Items[iLB]^) Do
      begin
        Objet := Liste.Items[iLB];
     
        With Form2 do
        begin
          edNom.Text := Objet^.elNom;
          edX.Text   := Inttostr(Objet^.elCooGalX);
          edY.Text   := Inttostr(Objet^.elCooGalY) ;
          edZ.Text   := Inttostr(Objet^.elCooGalZ);
        end;
        SaisieFicheToRecord(Objet);
      end;
    dernière remarque vous utilisez Freemem alors que les objets ont été créés par New dans ce cas c'est l'utilisation de Dispose est plus appropriée
    Dernière modification par Invité ; 19/05/2024 à 13h26.

  6. #6
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut
    Merci Volid pour tes remarques utiles!

    Citation Envoyé par Volid Voir le message
    Le problème est que les champs de Form2 ne sont pas initialisés par les données de l'enregistrement à modifier et gardent les anciennes valeurs saisies
    ...
    dernière remarque vous utilisez Freemem alors que les objets ont été créés par New dans ce cas c'est l'utilisation de Dispose est plus appropriée
    1. Oui bien sûr! Le fait d'initialiser le pointeur ne suffisait pas, il fallait que j'y rattache les données...
    2. Quand j'utilise New et Dispose, le compilateur n'aime pas, j'ai donc remplacé Dispose par FreeMen... Ce qui m'obligerait à utiliser sa contrepartie la fonction GetMem(size:ptruint):pointer ? J'avoue que je ne sais pas, ça fait partie des bizareries de Lazarus (est-ce une imprécision de leur part?) Le compilateur semble accepter New et FreeMem!
    Si tu as une explication, je suis preneur

    Je mets résolu pour l'instant

  7. #7
    Invité
    Invité(e)
    Par défaut
    j'ai donc remplacé Dispose par FreeMen... Ce qui m'obligerait à utiliser sa contrepartie la fonction GetMem(size:ptruint):pointer ?
    Dispose a besoin d'un pointeur typé pour finaliser la structure en cas il contient des champs de types protégés (string, tableaux dynamiques, interfaces et variants ) qui doivent être déréférencés avant la libération de la mémoire par Freemem, c'est pour éviter les fuites de mémoire..

    Dispose est l’équivalent de Finalize + Freemem

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    obj :=  Liste[ListBox1.ItemIndex]; 
    Dispose(obj);
    ou :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Dispose(PListeObjets(Liste[ListBox1.ItemIndex]));
    Pour un code plus robuste, TList offre la possibilité de gérer la libération automatiquement après les appel de Delete ou Clear par l'interception de l'événement Notify émis juste avant la suppression de l'élément .

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    unit Unit1;
    { Test exemple d'utilisation d'un TList avec une Structure Record par JLMat}
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, Types;
     
    Type
      {Champ des données du Catalogue des étoiles}
     
      PListeObjets = ^TObjetsCelestes;
      TObjetsCelestes =
        Record
          elNom   :String ;
          elCooGalX : Integer;
          elCooGalY : Integer;
          elCooGalZ : Integer;
        End;
     
      {Définition de TForm1 }
     
      { TForm1 }
     
      TForm1 = class(TForm)
        BtnAjouter  : TButton;
        BtnModifier : TButton;
        BtnSupprimer: TButton;
        BtnToutSupprimer: TButton;
        LbNombre    : TLabel;
        ListBox1    : TListBox;
        Panel1      : TPanel;
        StaticText1 : TStaticText;
        procedure BtnAjouterClick (Sender: TObject);
        procedure BtnModifierClick(Sender: TObject);
        procedure BtnSupprimerClick(Sender: TObject);
        procedure BtnToutSupprimerClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        function SaisieFicheToRecord(var Obj: PListeObjets):boolean;
        Procedure MAJAfficheListe;
      public
     
      end;
     
    var
      Form1 : TForm1;
      Liste : TList;
     
    {===============================================================================}
    implementation
    Uses Unit2;
    {$R *.lfm}
    {===============================================================================}
     
    type
        TObjList = class(TList)
        public
           procedure Notify(Ptr: Pointer; Action: TListNotification); override;
        end;
        procedure  TObjList.Notify(Ptr: Pointer; Action: TListNotification);
        begin
           if (Action = lnDeleted) and (Ptr <> nil) then
              Dispose(PListeObjets(Ptr));
        end;
    { TForm1 }
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Liste := TObjList.Create; // Création de la liste
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Form1.btnToutSupprimerClick(nil);
      Liste.Free;
    end;
     
    {--- Ajoute un Objet au Catalogue ---------------------------------------------}
    function ObjDisplayText(Obj: PListeObjets):string;
    begin
      if Obj <>  nil then
       with Obj^ do
         Result := Format('%-20s%5d%5d%5d',[elNom,elCooGalX,elCooGalY,elCooGalZ])
      else
         Result := '< liste vide >';
    end;
     
     
    {- Transfert les Saisies de la Fiche Form2 vers le Buffer des Objets de la Liste -}
    function TForm1.SaisieFicheToRecord(var Obj : PListeObjets):boolean;
    begin
      With TForm2.Create(nil) do  // creer une nouvelle form2
      try
        if Obj <> nil then
        with Obj^ do
        begin
          edNom.Text := elNom;
          edX.Text   := Inttostr(elCooGalX);
          edY.Text   := Inttostr(elCooGalY) ;
          edZ.Text   := Inttostr(elCooGalZ);
        end;
        Result := ShowModal = mrOK;
        if not Result then
           Exit;
     
        if Obj = nil then
           New(Obj);
     
        with Obj^ do
        begin
          elNom     := edNom.Text;
          elCooGalX := StrToInt(edX.Text);
          elCooGalY := StrToInt(edY.Text);
          elCooGalZ := StrToInt(edZ.Text);
        end;
      finally
        Free;
      end;
    end;
     
    {--- Affichage des Objets Célestes du Catalogue dans une ListBox --------------}
    Procedure TForm1.MAJAfficheListe;
      Var i : Integer;
    Begin
      ListBox1.Items.BeginUpdate;
      ListBox1.Items.Clear;
      For i := 0 To Liste.Count-1 Do
        ListBox1.Items.Add(ObjDisplayText(Liste[i]));
      ListBox1.Items.EndUpdate;
      lbNombre.Caption := IntToStr(Liste.Count);
    End;
     
    {--- Ajoute un Objet au Catalogue ---------------------------------------------}
    procedure TForm1.BtnAjouterClick(Sender: TObject);
     Var Objet : PListeObjets;
     DisplayTxt: string;
    begin
      Objet := nil;
      if SaisieFicheToRecord(Objet) then
      begin
        Liste.Add(Objet);
        DisplayTxt := ObjDisplayText(Objet);
        ListBox1.Items.Add(DisplayTxt);
      end;
    end;
     
    {--- Modifie un Objet du Catalogue --------------------------------------------}
    procedure TForm1.BtnModifierClick(Sender: TObject);
     var Objet : PListeObjets;
         iLB   : Integer;
    begin
      iLB := ListBox1.ItemIndex;
      if iLB < 0 then Exit;
     
      {Affichage de ses données et valeurs}
       Objet := Liste[iLB];
       if SaisieFicheToRecord(Objet) then
         ListBox1.Items[iLB] := ObjDisplayText(Objet);
    end;
     
    {--- Supprimer un élément de la Liste -----------------------------------------}
    procedure TForm1.BtnSupprimerClick(Sender: TObject);
    begin
      If ListBox1.ItemIndex < 0 then Exit;
      // on supprime de Liste d'abord pour garder le ItemIndex stable
      Liste.Delete(ListBox1.ItemIndex);
      ListBox1.Items.Delete(ListBox1.ItemIndex);
    end;
     
    {--- Suppression de tous les Objets de la Liste et libération mémoire --------}
    procedure TForm1.BtnToutSupprimerClick(Sender: TObject);
    begin
      Liste.Clear;
      ListBox1.Clear;
    end;
     
    end.

  8. #8
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut
    Ok Valid, merci

    je suis d'accord, c'est pas très propre de mélanger les Freemem et les New!

    j'étais justement en train de réfléchir à créer une class spécialement pour gérer la TList.
    d'autant qu'il faut que je puisse gérer des Double, ce qui complique un peu, mais ça sera un prochain post, si je n'y arrive pas...

    J'ai essayé ton code et j'y ai appris des choses en particulier sur les notifications.
    Finalement dans cette encapsulation, le compilateur n'a rien à redire, ça marche bien!

    Merci

  9. #9
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2013
    Messages
    362
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2013
    Messages : 362
    Points : 586
    Points
    586
    Billets dans le blog
    2
    Par défaut Classe générique de listes
    Citation Envoyé par Jlmat Voir le message
    Ok Valid, merci

    je suis d'accord, c'est pas très propre de mélanger les Freemem et les New!

    j'étais justement en train de réfléchir à créer une class spécialement pour gérer la TList.
    d'autant qu'il faut que je puisse gérer des Double, ce qui complique un peu, mais ça sera un prochain post, si je n'y arrive pas...

    J'ai essayé ton code et j'y ai appris des choses en particulier sur les notifications.
    Finalement dans cette encapsulation, le compilateur n'a rien à redire, ça marche bien!

    Merci
    Classe générique de listes

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
     
    // liste générique (fonctionne très bien)
    { TListeSimple }
    // Exceptions
    type EUndefinedFunctionProj = class(Exception);
    type TListeSimple<T> = class(TFPList)
      private
      public
        procedure ClearListe();
        function  GetNbElements(): integer; inline;
        procedure InsertElement(const Idx: integer; const E: T);
        procedure AddElement(const E: T);  // et Rros Minet
        function  GetFirstElement(): T; inline;
        function  GetElement(const Idx: integer): T; inline;
        function  GetLastElement(): T; inline;
        procedure PutElement(const Idx: integer; const E: T); inline;
        function  RemoveElement(const Idx: integer): boolean;
        function  RemoveLastElement(): boolean;
        procedure EnQueue(const E: T); inline; // file: Ajoute un entrant -- Synonyme de procedure AddElement();
        function  DeQueue(): T;                // file: extrait et supprime le premier entré (l'élément 0 est devant le guichet)
        procedure Push(const E: T); inline;    // Pile: Ajoute un élément -- Synonyme de AddElement()
        function  Pop(): T;                    // Pile: Extrait le dernier élément entré et le supprime de la liste
        procedure Compacter();
    end;     
     
    implementation
    implementation
    uses
      Dialogs,
      DGCDummyUnit; // Anti-erreur 'Fin du conde source non trouvée'
     
    { TListeSimple<T> }
    procedure TListeSimple<T>.ClearListe();
    var
      i, n: Integer;
    begin
      n := self.Count;
      if (n > 0) then
      begin
        for i := Count-1 downto 0 Do
        begin
          if (self.Items[i] <> Nil) then Dispose(self.Items[i]); // Libération
          self.Delete(i);                                        // Suppression de l'élément
        end;
        self.clear;
      end;
    end;
     
     
     
    function TListeSimple<T>.GetNbElements(): integer;
    begin
      Result := self.Count;
    end;
     
    procedure  TListeSimple<T>.InsertElement(const Idx: integer; const E: T);
    var pE: ^T;
    begin
      New(pE);
      pE^ := E;
      self.Insert(Idx, pE);
    end;
    procedure TListeSimple<T>.AddElement(const E: T);
    var pE: ^T;
    begin
      New(pE);
      pE^ := E;
      self.Add(pE);
    end;
     
    function TListeSimple<T>.GetFirstElement(): T;
    begin
      Result := T(Items[0]^);
    end;
     
    function TListeSimple<T>.GetElement(const Idx: integer): T;
    begin
      Result := T(Items[Idx]^);
    end;
     
    procedure TListeSimple<T>.PutElement(const Idx: integer; const E: T);
    begin
      try
        if (Idx < 0) then exit;
        T(Items[Idx]^) := E;
      except
      end;
    end;
     
    function TListeSimple<T>.RemoveElement(const Idx: integer): boolean;
    begin
      Result := False;
      try
        Dispose(self.Items[Idx]);
        self.Delete(Idx);
        Result := True;
      except
      end;
    end;
     
    function TListeSimple<T>.RemoveLastElement(): boolean;
    var
      Nb: Integer;
    begin
      Nb := self.Count;
      if (0 = Nb) then Exit(false);
      result := self.RemoveElement(Nb - 1);
    end;
     
    procedure TListeSimple<T>.EnQueue(const E: T);
    begin
      AddElement(E);
    end;
     
    function TListeSimple<T>.DeQueue(): T;
    begin
      Result := GetElement(0);
      RemoveElement(0);
    end;
     
    procedure TListeSimple<T>.Push(const E: T);
    begin
      AddElement(E);
    end;
     
    function TListeSimple<T>.Pop(): T;
    var
      n: Integer;
    begin
      n := GetNbElements();
      if (n > 0) then
      begin
        Result := GetElement(n-1);
        RemoveElement(n-1);
      end;
    end;
     
    procedure TListeSimple<T>.Compacter();
    begin
      self.Pack();
    end;
     
    function TListeSimple<T>.GetLastElement(): T;
    var n: integer;
    begin
      n := self.getNbElements();
      result := self.getElement(n-1);
    end;
    Dérivation de la classe: Exemple avec des points 3D

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    type  TPoint3Df = record
      X:  double;
      Y:  double;
      Z:  double;
    end; 
     
     
    type TListePoints3Df = class(TListeSimple<TPoint3Df>)
      private
      public
    end;
    Utilisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    var
      P: TPoint3df;
      LS: TListePoints3Df;
    begin
      LS := TListePoints3Df .Create;
      P.X := 403460.0; P.Y := 3089600.0 ; P.Z := 540.0;
      LS.AddElement(P);

  10. #10
    Membre averti
    Avatar de Jlmat
    Homme Profil pro
    Consultant en Ressources Humaines, Retraité passionné de programmation
    Inscrit en
    Avril 2008
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant en Ressources Humaines, Retraité passionné de programmation
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 319
    Points : 389
    Points
    389
    Par défaut
    Merci JP Cassou pour cette solution

    C'est du Delphi ou du Lazarus?
    Que signifie les guillements dans l'instruction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     type TListeSimple<T> = class(TFPList)
    Je ne conaissais pas le type TFPList spécialement dédié à la gestion des pointeurs.
    Mon compilateur n'accepte pas <T>, que dois-je déclarer comme unité supplémentaire?


    Citation Envoyé par JP CASSOU Voir le message
    Classe générique de listes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     - liste générique (fonctionne très bien)...
     - Dérivation de la classe: Exemple avec des points 3D...
    - Utilisation...
    J'étais en train d'écrire pour les Réels justement! ça parait sophistiqué comme solution, mais très intéressante..;
    bon, j'étudie tout ça

    A+

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 24/12/2009, 11h37
  2. Réponses: 1
    Dernier message: 18/09/2008, 01h10
  3. [Debutant]TString dans TList
    Par Ekik dans le forum Delphi
    Réponses: 1
    Dernier message: 30/05/2006, 10h38
  4. [MySQL] Problme de variables dans requete
    Par eown dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 11/04/2006, 18h05
  5. Pointer dans l'espace mémoriel
    Par Alfred12 dans le forum Langage
    Réponses: 5
    Dernier message: 01/04/2006, 12h26

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