60 votes

Comment déterminer si un tableau est initialisé dans VB6?

Le passage d'un tableau non dimensionné à la fonction Ubound du VB6 provoquera une erreur. Je souhaite donc vérifier s'il a déjà été dimensionné avant de tenter de vérifier sa limite supérieure. Comment puis-je faire cela?

24voto

GSerg Points 33571

J'utilise ceci:

 Public Declare Function GetMem4 Lib "msvbvm60" (ByVal pSrc As Long, ByVal pDst As Long) As Long
Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long

Public Function StrArrPtr(arr() As String, Optional ByVal IgnoreMe As Long = 0) As Long
  GetMem4 VarPtr(IgnoreMe) - 4, VarPtr(StrArrPtr)
End Function

Public Function UDTArrPtr(ByRef arr As Variant) As Long
  If VarType(arr) Or vbArray Then
    GetMem4 VarPtr(arr) + 8, VarPtr(UDTArrPtr)
  Else
    Err.Raise 5, , "Variant must contain array of user defined type"
  End If
End Function


Public Function ArrayExists(ByVal ppArray As Long) As Long
  GetMem4 ppArray, VarPtr(ArrayExists)
End Function
 

Usage:

 ? ArrayExists(ArrPtr(someArray))
 
 ? ArrayExists(StrArrPtr(someArrayOfStrings))
 
 ? ArrayExists(UDTArrPtr(someArrayOfUDTs))
 

Votre code semble faire la même chose (tester SAFEARRAY ** étant NULL), mais d'une manière que je considérerais comme un bogue du compilateur :)

22voto

raven Points 9396

J'ai juste pensé de celui-ci. Assez Simple, pas d'appels de l'API nécessaires. Pas de problèmes avec elle?

Public Function IsArrayInitialized(arr) As Boolean

  Dim rv As Long

  On Error Resume Next

  rv = UBound(arr)
  IsArrayInitialized = (Err.Number = 0)

End Function

Edit: j'ai fait découvrir une faille avec ce lié au comportement de la fonction de répartition (en fait je l'appellerais une faille dans la fonction de répartition). Prenez cet exemple:

Dim arr() As String

arr = Split(vbNullString, ",")
Debug.Print UBound(arr)

Quelle est la valeur de Ubound(arr) à ce point? C'est -1! Ainsi, le passage de cette matrice à cette IsArrayInitialized la fonction renvoie true, mais tenter d'accéder à des arr(0) provoquerait un indice en dehors de la plage d'erreur.

15voto

raven Points 9396

Voici ce que je suis allé avec. Ceci est similaire à GSerg de la réponse, mais utilise les mieux documentés CopyMemory la fonction de l'API et est entièrement autonome (il vous suffit de passer le tableau plutôt que de ArrPtr(array) pour cette fonction). Il utilise la fonction VarPtr, Microsoft met en garde contre l', mais c'est un XP-seule application, et ça marche, donc je ne suis pas concerné.

Oui, je sais que cette fonction accepte tout ce que vous jetez à lui, mais je vais laisser la vérification des erreurs comme exercice pour le lecteur.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Function ArrayIsInitialized(arr) As Boolean

  Dim memVal As Long

  CopyMemory memVal, ByVal VarPtr(arr) + 8, ByVal 4 'get pointer to array
  CopyMemory memVal, ByVal memVal, ByVal 4  'see if it points to an address...  
  ArrayIsInitialized = (memVal <> 0)        '...if it does, array is intialized

End Function

14voto

raven Points 9396

J'ai trouvé ça:

 Dim someArray() As Integer

If ((Not someArray) = -1) Then
  Debug.Print "this array is NOT initialized"
End If
 

Edit : RS Conley a souligné dans sa réponse que (Not someArray) retournera parfois 0, vous devez donc utiliser ((Not someArray) = -1).

9voto

RS Conley Points 6268

GSerg et Raven sont des méthodes non documentées, mais comme Visual BASIC 6 n'est plus en développement, ce n'est pas un problème. Cependant, l'exemple de Raven ne fonctionne pas sur toutes les machines. Vous devez tester comme ça.

Si (pas un tableau) = -1 alors

Sur certaines machines, il retournera un zéro sur d'autres, un nombre négatif élevé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X