Page 1 sur 1

Probleme de pointeurs (liste chainée)

Publié : mar. 28/déc./2004 13:06
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()

Publié : mar. 28/déc./2004 13:53
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.

Publié : mar. 28/déc./2004 14:19
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:

Publié : mar. 28/déc./2004 14:32
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.

Publié : mar. 28/déc./2004 14:42
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()

Publié : mar. 28/déc./2004 14:48
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: ...

Publié : mar. 28/déc./2004 15:30
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()

Publié : mar. 28/déc./2004 15:58
par nico
Pendant un moment tu m'a fais peur, excellent Lionel. :D

Publié : mar. 28/déc./2004 17:33
par lionel_om
nico a écrit :Pendant un moment tu m'a fais peur
Prkoi je t'ai fait peur ??? :roll:
Merci !!! :d

Publié : mar. 28/déc./2004 17:51
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

Publié : mer. 29/déc./2004 18:11
par lionel_om
merci ! :d

Demande d'Aide à Lionel

Publié : lun. 09/mai/2005 11:05
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