Probleme de pointeurs (liste chainée)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Probleme de pointeurs (liste chainée)

Message par lionel_om »

Bonjour a tous !!! :D
Je me suis amusé à voir comment marchés les pointeurs en Pure.

J'ai fait une structure Liste Chainée (Linkedlist) qui marche, mais le problème c'est qu'en modifiant le pointeur dans une fonction (Add, Delete ...) ne modifie pas le pointeur de l'objet dans le programme principal. Ainsi j'ai été obligé de faire ainsi : :cry:

Code : Tout sélectionner

*liste.LinkedList
*liste = Add(*liste,5)
Alors que je voudrais faire ceci :

Code : Tout sélectionner

*liste.LinkedList
Add(*liste,5)
Il n'y a aucune autre "fonctions" du style Shared, Global, ... qui ferait gardé la valeur de mon pointeur que j'ai modifié dans mes fonctions ??? :roll:

Voici mon code :

Code : Tout sélectionner




Structure Ennemi
  Energ.w
EndStructure



Structure LinkedList
  *Suiv.LinkedList
  *Prec.LinkedList
  Info.Ennemi
EndStructure



;- - - - - - - - - -  Les fonctions - - - - - - - - - -

Procedure Add(*m1.LinkedList, s.w)
  If *m1 = #Null
    *m1 = AllocateMemory(SizeOf(LinkedList))
    *m1\Info\Energ = s
    ProcedureReturn (*m1)
  EndIf

  If (*m1\Suiv <> #Null)
    Add(*m1\Suiv, s)
  Else
    *m2.LinkedList = AllocateMemory(SizeOf(LinkedList))
    *m2\Prec = *m1
    *m2\Info\Energ = s
    *m2\Suiv = #Null
    *m1\Suiv = *m2
  EndIf

  ProcedureReturn *m1
EndProcedure


Procedure Affiche(*m.LinkedList)
  If *m <> #Null
    PrintN(Str(*m\Info\Energ) + "  " + Str(*m) + "  " + Str(*m\Prec) + "  " + Str(*m\Suiv))
    Affiche(*m\Suiv)
  EndIf
EndProcedure


Procedure.w Count(*m.LinkedList)
  If *m <> #Null
    ProcedureReturn(Count(*m\Suiv)+1)
  EndIf
EndProcedure


Procedure Delete(*m.LinkedList, n.w)
Shared
  If n<0 Or ( *m\Suiv = #Null And n>0)
    PrintN("Erreur d'indice")
    ProcedureReturn(*m)
  EndIf

  If n>0
    Delete(*m\Suiv, n-1)
  Else
    If *m\Suiv <> #Null And *m\Prec <> #Null
      PokeL(*m\Suiv+4, *m\Prec)
      PokeL(*m\Prec, *m\Suiv)
      FreeMemory(*m)
    ElseIf *m\Suiv = #Null And *m\Prec = #Null  ; Un seul élément
      FreeMemory(*m)
      *m = #Null
    ElseIf *m\Suiv = #Null ;En fin de liste
      PokeL(*m\Prec, #Null)
      FreeMemory(*m)
    Else  ; En début de liste
      PokeL(*m\Suiv+4, #Null)
      *m = PeekL(*m)
      FreeMemory(*m\Prec)
    EndIf
  EndIf
    ProcedureReturn(*m)
  
EndProcedure


Procedure DeleteLast(*m.LinkedList)

  If *m\Suiv <> #Null
    DeleteLast(*m\Suiv)
  Else
    If *m\Prec = #Null  ; Un seul élément
      FreeMemory(*m)
      *m = #Null
    Else ;En fin de liste
      PokeL(*m\Prec, #Null)
      FreeMemory(*m)
    EndIf
  EndIf
    ProcedureReturn(*m)

EndProcedure


;- - - - - - - - - - Programme principal - - - - - - - - - - - -

OpenConsole()


*mst.LinkedList = #Null
*mst = Add(*mst,5)
*mst = Add(*mst,6)
*mst = Add(*mst,7)
*mst = Add(*mst,3)
PrintN("nbr : " + Str(Count(*mst)))
  PrintN("Affichage"): Affiche(*mst): PrintN("")

  
  *mst = DeleteLast(*mst)
  PrintN("Affichage"): Affiche(*mst): PrintN("")

  *mst = DeleteLast(*mst)
  PrintN("Affichage"): Affiche(*mst): PrintN("")

  *mst = Delete(*mst, 0)
  PrintN("Affichage"): Affiche(*mst): PrintN("")

  *mst = DeleteLast(*mst)
  PrintN("Affichage"): Affiche(*mst): PrintN("")


Input()
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Au lieu d'envoyer le pointeur, envoie l'adresse du pointeur @*mst, ainsi tu pourras réécrire la valeur du nouveau pointeur directement dans l'adresse du pointeur.
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

J'essaye mais ca marche pas ! :cry:
Ma fonction affcihe me donne ceci :
5 8920720 0 8920744
6 8920744 8920720 8920768
7 8920768 8920744 8920792
3 8920792 8920768 0
; Elts, Adr bloc, Adr pointeur Précédent, Adr pointeur Suivant
alors que si je fais Add(@mst, 6) et que dans la fonction j'affiche la valeur du pointeur, ou de l'adresse, j'obtient des valeurs aux alentours de 420000 et 1250000

Donc les valeurs ne sont plus du tout du mm ordre, c sans doute leur valeur dans la pile...
Merci pour ta réponse si rapide en tt cas :wink:
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Code : Tout sélectionner

alors que si je fais Add(@mst, 6) et que dans la fonction j'affiche la valeur du pointeur, ou de l'adresse, j'obtient des valeurs aux alentours de 420000 et 1250000 
Non, faire Add(@*mst, 6) mais cela implique de réécrire les procédures bien sûr.

J'ai essayé, mais le problème, c'est qu'il faudrait initialiser le pointeur avant de lui ajouter des valeurs.

Du genre *mst.LinkedList = init() pour récupérer le pointeur du début de la linkedlist.

Si tu pouvais faire ça.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je viens de finir un bout de code qui s'approche:

Code : Tout sélectionner

Structure Ennemi 
  Energ.w 
EndStructure 

Structure LinkedList 
  *Suiv.LinkedList 
  *Prec.LinkedList 
  Info.Ennemi 
EndStructure 

;- - - - - - - - - -  Les fonctions - - - - - - - - - - 

Procedure init(*m1.LinkedList, s.w) 
  If *m1 = #Null 
    *m1 = AllocateMemory(SizeOf(LinkedList)) 
    *m1\Info\Energ = s ; faudrait supprimer ça
    ProcedureReturn (*m1) 
  EndIf 
  ProcedureReturn *m1 
EndProcedure

Procedure Add(adresse1, s.w)
  *m1.LinkedList=PeekL(adresse1)
  
  If (*m1\Suiv <> #Null) 
    Add(*m1\Suiv, s) 
  Else 
    *m2.LinkedList = AllocateMemory(SizeOf(LinkedList)) 
    *m2\Prec = *m1 
    *m2\Info\Energ = s 
    *m2\Suiv = #Null 
    *m1\Suiv = *m2 
  EndIf 
  PokeL(adresse1,*m2)
  ProcedureReturn 1 
EndProcedure 


Procedure Affiche(*m.LinkedList) 
  If *m <> #Null 
    PrintN(Str(*m\Info\Energ) + "  " + Str(*m) + "  " + Str(*m\Prec) + "  " + Str(*m\Suiv)) 
    Affiche(*m\Suiv) 
  EndIf 
EndProcedure 


Procedure.w Count(*m.LinkedList) 
  If *m <> #Null 
    ProcedureReturn(Count(*m\Suiv)+1) 
  EndIf 
EndProcedure 


;- - - - - - - - - - Programme principal - - - - - - - - - - - - 

OpenConsole() 

*mst.LinkedList = #Null 
*mst = init(*mst,5); si on pouvait éviter ça comme je t'ai dit.
*origine=*mst ; sauvegarder le pointeur d'origine

adresse= @*mst
Add(adresse,6) 
Add(adresse,7) 
Add(adresse,3) 
PrintN("nbr : " + Str(Count(*origine))) 
PrintN("Affichage"): Affiche(*origine): PrintN("") 

Input()
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

daccord

J'ai écrit la prcédure Init() :

Code : Tout sélectionner

Procedure Init(*m.LinkedList)
  ProcedureReturn( PeekL(*m) )
EndProcedure
pas trop dure !!! :lol:

par contre je ne vois pas ce qu'il faut renvoyer ou faire dans la fonction pour que le changement d'adresse mémoire s'effectue sur le pointeur du prog principal :cry: ...
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Merci Nico, j'ai compris comment ca marche :

voici mon code modifié !!! :

Code : Tout sélectionner

Structure Ennemi
  Energ.w
EndStructure



Structure LinkedList
  *Suiv.LinkedList
  *Prec.LinkedList
  Info.Ennemi
EndStructure



;- - - - - - - - - -  Les fonctions - - - - - - - - - -

Procedure Add(*adresse, s.w)
  *m1.LinkedList = PeekL(*adresse)

  If *m1 = #Null          ; Liste vide
    *m1 = AllocateMemory(SizeOf(LinkedList))
    *m1\Info\Energ = s
    PokeL(*adresse,*m1)
  ElseIf (*m1\Suiv <> #Null)  ; on au milieu de la liste
    Add(@*m1\Suiv, s)
  Else                   ; on est en fin de liste
    *m2.LinkedList = AllocateMemory(SizeOf(LinkedList))
    *m2\Prec = *m1
    *m2\Info\Energ = s
    *m2\Suiv = #Null
    *m1\Suiv = *m2
  EndIf

EndProcedure


Procedure Affiche(*m.LinkedList)
  If *m <> #Null
    PrintN(Str(*m\Info\Energ) + "  " + Str(*m) + "  " + Str(*m\Prec) + "  " + Str(*m\Suiv))
    Affiche(*m\Suiv)
  EndIf
EndProcedure


Procedure.w Count(*m.LinkedList)
  If *m <> #Null
    ProcedureReturn(Count(*m\Suiv)+1)
  EndIf
EndProcedure




Procedure Delete(*adresse, n.w)
  *m.LinkedList = PeekL(*adresse)

  If n<0 Or ( *m\Suiv = #Null And n>0)
    PrintN("Erreur d'indice")
    ProcedureReturn 0
  EndIf
  
  If *m = #Null
    PrintN("Liste vide")
    ProcedureReturn 0
  EndIf
  
  If n>0
    Delete(@*m\Suiv, n-1)
  Else
    If *m\Suiv <> #Null And *m\Prec <> #Null  ; dans la liste
      PokeL(*m\Suiv+4, *m\Prec)
      PokeL(*m\Prec, *m\Suiv)
      FreeMemory(*m)
    ElseIf *m\Suiv = #Null And *m\Prec = #Null  ; Un seul élément
      FreeMemory(*m)
      PokeL(*adresse,#Null)
    ElseIf *m\Suiv = #Null ;En fin de liste
      PokeL(*m\Prec, #Null)
      FreeMemory(*m)
    Else                ; En début de liste
      PokeL(*m\Suiv+4, #Null)
      PokeL(*adresse,PeekL(*m))
      FreeMemory(*m\Prec)
    EndIf
  EndIf
    ProcedureReturn 1
  
EndProcedure


Procedure DeleteLast(*adresse)
  *m.LinkedList = PeekL(*adresse)
  If *m = #Null
    PrintN("Liste vide")
    ProcedureReturn(1)
  EndIf

  If *m\Suiv <> #Null ; on est au milieu de la liste
    DeleteLast(@*m\Suiv)
  Else
    If *m\Prec = #Null  ; Un seul élément
      FreeMemory(*m)
      PokeL(*adresse,#Null)
    Else                ;En fin de liste
      PokeL(*m\Prec, #Null)
      PokeL(*adresse,PeekL(*m))
      FreeMemory(*m)
    EndIf
  EndIf
    ProcedureReturn(1)

EndProcedure


;- - - - - - - - - - Programme principal - - - - - - - - - - - -

OpenConsole()


*mst.LinkedList = #Null
Add(@*mst,5)
Add(@*mst,6)
Add(@*mst,7)
Add(@*mst,3)
  PrintN("nbr : " + Str(Count(*mst)))
  PrintN("Affichage"): Affiche(*mst): PrintN("")

  Delete(@*mst,0)
  PrintN("Affichage"): Affiche(*mst): PrintN("")
  Delete(@*mst,0)
  PrintN("Affichage"): Affiche(*mst): PrintN("")
  Delete(@*mst,4)
  DeleteLast(@*mst)
  PrintN("Affichage"): Affiche(*mst): PrintN("")
  DeleteLast(@*mst)
  DeleteLast(@*mst)
  PrintN("Affichage"): Affiche(*mst): PrintN("")
  
Input()
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Pendant un moment tu m'a fais peur, excellent Lionel. :D
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

nico a écrit :Pendant un moment tu m'a fais peur
Prkoi je t'ai fait peur ??? :roll:
Merci !!! :d
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Quand j'ai vu ta procédure, je me suis dit, il se ballade avec les pointeurs, et tu n'avais pas l'air de comprendre mes réponses.... et puis finalement je vois que tu maitrises.

:D
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

merci ! :d
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Cagou-77
Messages : 79
Inscription : dim. 15/août/2004 13:27

Demande d'Aide à Lionel

Message par Cagou-77 »

Salut,

j'ai modifier ton code pour l'adapter à mon prog,
mais il me manque une fonction de recherche dans la liste et je n'y arrive pas pourrait-tu m'aider si te plait .
ex:

Structure ListBox
ID.l
Value.s
EndStructure

Structure LinkedList
*Suiv.LinkedList
*Prec.LinkedList
Info.ListBox
EndStructure

Procedure.s FindItem(*m.LinkedList, n.w)
If *m <> #Null
If *m\Info\ID <> n
FindItem( *m\Suiv, n.w )
Else
????
EndIf
EndIf
ProcedureReturn *m\Info\Value
EndProcedure

je n'arrive pas à sortir de la boucle
merci d'Avance pour ton aide

Michel
Répondre