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 :

Creation d'une class de liste chainé, besoin d'un petit coup de main


Sujet :

Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    Points : 137
    Points
    137
    Par défaut Creation d'une class de liste chainé, besoin d'un petit coup de main
    Bonjour,
    Je suis en train de créer une classe pour faire une liste chainée qui permet de passer d'un élément a l'autre (noeud) dans les deux sens.
    N1<-->N2<-->N3...
    Pour aller de N1 vers N2 on utlise GetNoeudNext sur N1.
    Pour aller de N2 vers N1 on utlise GetNoeudBefore sur N2.

    voila, ou j'en suis dans son implémentation:

    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
    interface
    type
      TNoeud = class(TObject)
      private
        Nom : string;
        NoeudPrecedent: TNoeud;
        NoeudSuivant: TNoeud;
      public
        constructor Create(Param:string);
        destructor Destroy;
        procedure AddChild(Name:string);
      published
        property Name:string read Nom write Nom;
        property GetNoeudNext:TNoeud read NoeudSuivant write NoeudSuivant;
        property GetNoeudBefore:TNoeud read NoeudPrecedent write NoeudPrecedent;
    end;
     
     
    implementation
     
    constructor TNoeud.Create(Param:string);
    begin
      Nom:=Param;
      NoeudSuivant:=nil;
      NoeudPrecedent:=nil;
    end;
     
    destructor TNoeud.Destroy;
    begin
    end;
     
    procedure TNoeud.ChangeName(Value:string);
    begin
      Nom:=Value;
    end;
     
    procedure TNoeud.AddChild(Name:string);
    begin
      NoeudSuivant:=TNoeud.Create(Name,False,True);
      //NoeudSuivant.NoeudPrecedent:= ??doit pointé sur N1??
    end;
     
    end.
    Maintenant je vous montre comment je compte l'utiliser:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var
      //declaration de la variable ex qui est une liste chainée
      ex:TNoeud;
    begin
      //creation du premier noeud de ma liste chainée
      ex:=TNoeud.create('N1');
      //creation du second noeud de la liste chainée
      ex.AddChild('N2');
      //On se position sur le Noeud N2
      ex:=ex.GetNoeudNext;
      //On se reposition sur le Noeud N1
      ex:=ex.GetNoeudBefore;
    end;
    Comme vous l'avez compris la derniere ligne ne fonctionne pas. En effet j'ai pas reussi a faire pointé la varitable NoeudPrecedent dans la procedure TNoeud.AddChild(Name:string) sur N1.
    Dans la procedure on a access au champ du noeud comme "Name" par exemple. Mais moi ce que j'aimerai c avoir access a son address...
    Quelqu'un voit il comment il faudrai faire?

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    procedure TNoeud.AddChild(Name:string);
    begin
    NoeudSuivant:=TNoeud.Create(Name,False,True);
    //NoeudSuivant.NoeudPrecedent:= ??doit pointé sur N1??
    end;
    Tu ne vas pas t'en sortir comme cela, surtout qu'il faut instancier au préalable les objets.

    Vite fait car je n'ai pas le temps, un début de piste

    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
    TList = class
      private
       FCount: integer;
       FDebut: TNoeud;
       FFin: TNoeud;
      public
        constructor Create;override;
        destructor Destroy;override;
        function GetNode(Idx: Integer): TNoeud;
        function SetNode(n:TNoeud): integer;  
      property
       Count
       Debut
       Fin  
    end;
     
      TNoeud = class
       end;
     
      Noeud := TNoeud.Create;
      TList.Add(Noeud);
    avec un test: si 1er noeud alors CeNoeud.prec = nil;

    Sinon il ya une TList, dans classes.pas, qui est bien codée.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    Points : 137
    Points
    137
    Par défaut
    Merci d'avoir répondu a ma requete mais j'ai besoin de faire cette classe ainsi pour mon application. J'y suis presque...
    Pour ce qui est le l'intencier ce n'est pas un souci.
    Il me faut juste completer cette procedure:
    procedure TNoeud.AddChild(Name:string);
    begin
    NoeudSuivant:=TNoeud.Create(Name); (L1)
    //NoeudSuivant.NoeudPrecedent:= ??doit pointé sur N1?? (L2)
    end;

    Par example, si tu parts du noeud N1 en faisaint N1.AddChild('N2') grace à la première ligne (cf L1), j'aurai le champ N1.NoeudSuivant qui pointera sur N2.
    N2 sera crée lors de ce même momment.
    Au momment ou N2 est cré on a:
    - N2.NoeudSuivant égale a Nil ce qui est parfait vu qu'il est le dernier maillon de la liste chainée.
    - N2.NoeudPrecedent égale a Nil car il vient juste d'etre créer. Or comme N2 est le suivant de N1, on a N1 qui est le precedent de N2.
    ==>il faut donc affecter au precedent de N2 l'adresse de N1. C se que je tente de faire a la ligne L2.
    Le Precedent de N2 s'ecrit "NoeudSuivant.NoeudPrecedent".
    (vu que N2=N1.NoeudSuivant)
    Jusque la c cool, maintenant il me reste plus qu'a le faire pointé sur N1.
    Malheureusement pour moi je suis confronté à Deux problemes:
    1) Je ne sais pas comment recupere l'adresse de N1?
    En effet j'ai access a tout les 'private' de N1 mais pas a N1 lui même.
    Quelqu'un sais t il comment avoir access dans la procedure à l'intance sur laquelle elle est appliqué? (Dans notre exemple N1)
    2) Une fois que l'on sera comment acceder a N1 on pourait croire qu'il suffira de faire:
    NoeudSuivant.NoeudPrecedent:= N1
    Mais le souci ce que il me recopira N1 alors que moi je ne veux pas qui me recopie N1 mais je veux que se champ pointe sur N1.
    Faut il obligatoirement que je change le champ NoeudPrecedent qui est un Tnoeud en un pointeur de Tnoeud?
    J'ai essayer de faire des pointeurs de classe mais j'ai pas reussi. Peut on m'aider a ce sujet.

    J'aimerai Vraimant que l'on me reponde a ces 2 dernieres questions et que l'on me propose pas une solution qui me permetrai de faire une liste chainé par un autre moyen.
    Je pense que pour repondre a ces 2 question il faut des personnes qui touchent gravent en class et en pointeur. Avis au killer en Delpi, ca me sauverait la vie!

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Quelqu'un sais t il comment avoir access dans la procedure à l'intance sur laquelle elle est appliqué
    réponse: Self.
    C'est l'équivalement de this en c++

  5. #5
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 770
    Points
    2 770
    Par défaut
    le mieu est de voir les sources de delphi pour le TStrings
    bon chance
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    Points : 137
    Points
    137
    Par défaut
    Merci Fabrice, j'ai utlise l'instruction que tu ma donné pour compler ma fonction et ca marche nickel!

    Voila ce que ca donne:

    procedure TNoeud.AddChild(Name:string);
    begin
    NoeudSuivant:=TNoeud.Create(Name);
    NoeudSuivant.NoeudPrecedent:=self;
    end;

    J'ai fait un petit test pour m'assurer que ma classe fonctionne correctement, le voici:

    procedure TForm1.Button1Click(Sender: TObject);
    var
    ex:TNoeud;
    a:string;
    begin
    ex:=TNoeud.create('N1');
    ex.AddChild('N2');
    ex.GetNoeudNext.AddChild('N3');
    ex:=ex.GetNoeudNext;
    ex.GetNoeudNext.AddChild('N4');
    ex:=ex.GetNoeudBefore;
    a:=a+'/'+ex.Name; //N1
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N2
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N3
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N4
    ex:=ex.GetNoeudBefore.GetNoeudBefore.GetNoeudBefore; //retour a N1
    ex.ChangeName('N1P');
    ex.GetNoeudNext.ChangeName('N2P');
    ex.GetNoeudNext.GetNoeudNext.ChangeName('N3P');
    a:=a+' - '+ex.Name; //N1P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N2P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N3P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N4
    ex:=ex.GetNoeudBefore.GetNoeudBefore.GetNoeudBefore;
    a:=a+' - '+ex.Name; //N1P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N2P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N3P
    ex:=ex.GetNoeudNext;
    a:=a+'/'+ex.Name; //N4
    ex:=ex.GetNoeudBefore.GetNoeudBefore.GetNoeudBefore;
    a:=a+' - '+ex.Name; //N1P
    a:=a+'/'+ex.GetNoeudNext.Name; //N2P
    a:=a+'/'+ex.GetNoeudNext.GetNoeudNext.Name; //N3P
    a:=a+'/'+ex.GetNoeudNext.GetNoeudNext.GetNoeudNext.Name; //N4

    Memo1.Text:=a;
    end;

    Lorsque j'execute le programme j'obtiens dans le MemO:
    /N1/N2/N3/N4 - N1P/N2P/N3P/N4 - N1P/N2P/N3P/N4 - N1P/N2P/N3P/N4
    C'est parfait j'ai fait 3 allée retour dans ma liste chainé preuve que les noeuds sont bien connecté. De plus, j'ai changé les noms des noeuds en court de route grace a la nouvelle procedure ChangeName que je viens d'implémentée pour etre sure que l'on se deplace bien sur ces noeuds.

    Donc pour conclure, Ca marche nickel! Merci fabrice!
    Cependant j'avoue qu'il y a un dernier point qui me m'embete. Je suis pas sur d'avoir des bien compris pourquoi ca marché. peux tu m'expliquer un peu mieux le mécanisme qui s'oppère...

    Si on dise que:
    -> represente GetNoeudNext
    <- represent GetNoeudBefore

    Lorsque je crée N1:
    ex:=TNoeud.create('N1');

    on a:
    N1 -> nil
    <- nil

    ensuite losque je crée N2:
    ex.AddChild('N2');

    La premmière ligne de AddChild qui est NoeudSuivant:=TNoeud.Create(Name) fait que l'on a:
    N1 -> N2 -> nil
    <- nil
    <- nil

    Et ensuite a la 2eme ligne de AddChild on a NoeudSuivant.NoeudPrecedent:=self et la je suis pas sure de comprendre ce qui ce passe. pour moi il devrait faire:

    N1 -> N2 -> nil
    <- N1 ->nil
    <-nil
    <- nil

    En effet j'ai fait une simple copie. Alors que en reallité on a le champ GetNoeudBefore de N2 qui pointe bien sur N1:

    N1 -> N2 -> nil
    ^ <--|
    | <- nil |
    --------------

    Je le sais car dans mon exemple (test) j'ai fait 3 allé-retour et j'ai même changé les nom des noeuds et que quand je repasse dedans c bien eu.

    J'aimerai vraimant bien comprendre le mécanisme qui s'oppaire.
    Pk il ne m'a pas fait une simple copie de N1 mais qui m'as bien fait pointé le champ GetNoeudBefore de N2 sur N1?

  7. #7
    Membre chevronné Avatar de philnext
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 552
    Points : 1 780
    Points
    1 780
    Par défaut
    En fait la question, qui a déja été posée implicitement dans ce post, c'est : pourquoi passer ton temps à refaire ce qui existe déja (dans les TList ou les TStringList entre autres) ?
    Pour mettre en oeuvre ces solutions tu en as pour 1/2 heure et en plus tu es sûr que ça marche...

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Pk il ne m'a pas fait une simple copie de N1 mais qui m'as bien fait pointé le champ GetNoeudBefore de N2 sur N1?
    Quand tu manipules des objets, en réalité tu manipules des pointeurs sur ces objects.Delphi cache l'usage de ces pointeurs pour faciliter la manipulation des objets.
    Dans le cas d'une copie comme objet1 := objet2; les 2 objets pointent sur la même zone mémoire. Modifier l'un c'est modifier l'autre.
    Self, déclaré dans une procedure, représente un pointeur sur l'objet possédant cette procedure.
    Self représente l'objet en cours.

    Pour faire des copies d'objets il est préférable de dériver de TPersistent et non de TObject, puis surcharger les méthodes Assign et AssignTo.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     TC1 = class(TPersistent)
      public
       nom: string;
       Constructor Create(Name: string);
       procedure AssignTo(Dest: TPersistent); override;
       procedure Assign(Source: TPersistent);
      end;
    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
    procedure TC1.Assign(Source: TPersistent);
    begin
      Self.Nom := (Source as TC1).Nom;
    end;
     
    procedure TC1.AssignTo(Dest: TPersistent);
    begin
      inherited;
      if Dest is TC1 then
        (Dest as TC1).Nom := Self.Nom;
    end;
     
    constructor TC1.Create(Name: string);
    begin
      Nom := Name;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      C1 := TC1.Create('riri');
      C2 := TC1.Create('fifi');
      c2.Assign(C1);
      ShowMessage(C2.Nom);
      C3.Nom := 'loulou';
      ShowMessage(c1.Nom);end;

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    Points : 137
    Points
    137
    Par défaut
    Merci fabrice, tu m'as repondu a toutes mes questions.
    Franchement, respect total.

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

Discussions similaires

  1. Besoin d'un petit coup de main avec Reflection
    Par teddyalbina dans le forum C#
    Réponses: 1
    Dernier message: 18/11/2008, 00h54
  2. Besoin d'un petit coup de main en algorithmie :D
    Par nikofybc dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 21/07/2008, 19h50
  3. Besoin d'un petit coup de main avec les hash
    Par scaleo dans le forum Langage
    Réponses: 6
    Dernier message: 31/05/2006, 23h12
  4. [DEBUTANT] Besoin d'un petit coup de main
    Par rantanplan08 dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 01/04/2006, 12h09
  5. UPDATE trop compliqué, besoin d'un petit coup de main ;)
    Par pwangen dans le forum Requêtes
    Réponses: 1
    Dernier message: 17/02/2006, 11h16

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