Les choses à ne pas faire

Informations pour bien débuter en PureBasic
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Les choses à ne pas faire

Message par Guimauve »

Bonjour à tous,

Afin d'aider les débutants je propose de mettre ici les exemples de code fonctionnel mais qui sont une très mauvaise pratique. L'idée n'est pas de ridiculiser qui que ce soit, l'ennui c'est parfois on me demande en message privé de corriger des codes et je vois, n'ayons pas peur des mots, des horreurs, des petits canapés de chez Dracula et j'en passe. Donc j'ouvre le bal ...

Le redimensionnement d'un tableau dans une boucle :

Code : Tout sélectionner

Dim MonTableauA.s(25)
Dim MonTableauB.s(25)
Dim MonTableauC.s(25)

Flag = #True

If Flag = #True
  
  MonMax = 500
  
  ReDim MonTableauA(0)
  ReDim MonTableauB(0)
  ReDim MonTableauC(0)
  
  For Index = 1 To MonMax
    
    ReDim MonTableauA(Index)
    ReDim MonTableauB(Index)
    ReDim MonTableauC(Index)
    
    ; On fait divers traitement avec les tableaux
    ; ...
    
  Next
  
EndIf 
AYOYE !!!!

Si on regarde le code précédent il y a une variable (MonMax) qui est initialisé à 500 après le If ensuite on ReDim les 3 tableaux à zéro puis on entre dans la boucle pour redimensionner 499 fois les 3 tableaux. Si on ignore la quantité de donnée, l'utilisation d'une liste chaînée est préférable à un tableau mais bon ce n'est pas le cas dans l'exemple, la quantité de données est connue. Dans un cas de figure comme celui-ci aurait du être programmé comme suit :

Code : Tout sélectionner

Dim MonTableauA.s(25)
Dim MonTableauB.s(25)
Dim MonTableauC.s(25)

Flag = #True

If Flag = #True
  
  MonMax = 500
  
  ReDim MonTableauA(MonMax)
  ReDim MonTableauB(MonMax)
  ReDim MonTableauC(MonMax)
  
  For Index = 1 To MonMax
    
    ; On fait divers traitement avec les tableaux
    ; ...
    
  Next
  
EndIf 
OH OUI !!!

Là on redimensionne une seule fois les tableaux et on obtient le même résultat sans faire travailler le processeur pour rien.

Si j'ai d'autres exemples du genre, je les ajouterai au fur et à mesure. Si d'autres programmeurs expérimentés avec PB ont des exemples du genre ajouté les, cela pourra aider les débutants à ne pas faire les mêmes erreurs.

A+
Guimauve
Dernière modification par Guimauve le ven. 15/juil./2011 4:50, modifié 2 fois.
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Re: Les choses à ne pas faire

Message par Guimauve »

Tableau structuré et lecture sur fichier

Le contexte est tel que l'on veut initialiser un tableau avec des valeurs lues dans un fichier binaire. La structure statique, elle ne contient ni tableau dynamique, ni liste chaînée, ni map, ni chaîne de caractère donc pas de problème.

Code : Tout sélectionner

Structure MaStructure
  
  Champs01.w
  Champs02.w
  Champs03.w
  Champs04.w
  Champs05.w
  Champs06.w
  Champs07.w
  
EndStructure

Global Dim MonTableau.MaStructure(0)

Procedure ChargerMonTableau(NoFichier.l, NomFichier.s)
  
  Protected Temporaire.MaStructure
  
  If ReadFile(NoFichier, NomFichier)
    
    Max = ReadLong(NoFichier)
    ReDim MonTableau(Max)
    
    For Index = 0 To Max
      
      ReadData(NoFichier, Temporaire, SizeOf(MaStructure))
      MonTableau(Index)\Champs01 = Temporaire\Champs01
      MonTableau(Index)\Champs02 = Temporaire\Champs02
      MonTableau(Index)\Champs03 = Temporaire\Champs03
      MonTableau(Index)\Champs04 = Temporaire\Champs04
      MonTableau(Index)\Champs05 = Temporaire\Champs05
      MonTableau(Index)\Champs06 = Temporaire\Champs06
      MonTableau(Index)\Champs07 = Temporaire\Champs07
      
      ; Autre traitement à faire avant de passer à l'élément suivant

    Next
    
    CloseFile(NoFichier)
    
  EndIf 
  
EndProcedure
La procédure de chargement depuis le fichier contient la variable Protected Temporaire.MaStructure qui est parfaitement inutile. En effet, il est inutile de passer par une variable temporaire pour lire les données pour ensuite les copier dans un index dans le tableau.

Code : Tout sélectionner

Structure MaStructure
  
  Champs01.w
  Champs02.w
  Champs03.w
  Champs04.w
  Champs05.w
  Champs06.w
  Champs07.w
  
EndStructure

Global Dim MonTableau.MaStructure(0)

Procedure ChargerMonTableau(NoFichier.l, NomFichier.s)
  
  If ReadFile(NoFichier, NomFichier)
    
    Max = ReadLong(NoFichier)
    ReDim MonTableau(Max)
    
    For Index = 0 To Max
      
      ReadData(NoFichier, MonTableau(Index), SizeOf(MaStructure))
      
      ; Autre traitement à faire avant de passer à l'élément suivant
      
    Next
    
    CloseFile(NoFichier)
    
  EndIf 
  
EndProcedure
De cette façon le code n'est pas pollué par des variables inutiles. Attention, je ne dis pas qu'il ne faut pas utiliser de variables temporaires pour faire des traitements lors de la lecture sur fichier. La variable Max qui sert à redimensionner le tableau et contrôler la boucle est une variable qui est nécessaire.

A+
Guimauve
Dernière modification par Guimauve le dim. 10/juil./2011 21:42, modifié 1 fois.
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Re: Les choses à ne pas faire

Message par Guimauve »

Allocation mémoire

Ici le contexte est de faire une allocation mémoire dont la taille est déterminé par une valeur contenue dans un structure de donnée ce qui est très bien. Cependant, il ne faut jamais mettre un "@" devant le nom de la structure comme dans le cas de la Mesh02 de l'exemple de code ci-dessous :

Code : Tout sélectionner

Structure Mesh
  
  VertexCount.l
  Vertex.i
  
EndStructure

Mesh01.Mesh\VertexCount = 25
Mesh01\Vertex = AllocateMemory(Mesh01\VertexCount * 3 * SizeOf(Double))

Mesh02.Mesh\VertexCount = 25
Mesh02\Vertex = AllocateMemory(@Mesh02\VertexCount * 3 * SizeOf(Double))

Debug "MemorySize(Mesh01\Vertex) = " + Str(MemorySize(Mesh01\Vertex))
Debug "MemorySize(Mesh01\Vertex) = " + Str(MemorySize(Mesh02\Vertex))

Debug "Mesh01\VertexCount = " + Str(Mesh01\VertexCount)
Debug "Mesh02\VertexCount = " + Str(Mesh02\VertexCount)
Debug "@Mesh02\VertexCount = " + Str(@Mesh02\VertexCount)
On voudrait que les Mesh01 et Mesh02 est le même nombre de vertices et donc la même taille mémoire. Lorsqu'on lance le code ci-haut le déboggeur affiche :

Code : Tout sélectionner

MemorySize(Mesh01\Vertex) = 600
MemorySize(Mesh01\Vertex) = 157528032
Mesh01\VertexCount = 25
Mesh02\VertexCount = 25
@Mesh02\VertexCount = 6563668
En ajoutant un @ le nombre de vertices passe de 25 à 6563668, c'est à dire le numéro de l'adresse mémoire et bien entendu ce n'est pas ce que l'on désir faire.
De plus, le faux nombre de vertices changera d'un ordinateur à un autre et même d'un lancement de son programme à un autre. Donc jamais de @ devant une variable dans un AllocateMemory().

A+
Guimauve
Répondre