Soyez le premier à donner votre avis sur cette source.
Vue 3 433 fois - Téléchargée 156 fois
Attribute VB_Name = "TableBool" ' REDLUPUS 2004 : manipulations de bits dans des tables. ' 1 - Permet de réduire la place occupée (jusqu'à plus de 90%) par ' des indicateurs booléens, si l'on doit en manipuler beaucoup. ' 2 - Permet de travailler sur des "ensembles". ' remarque : ' - La partie "Appels pour le positionnement des bits" est ' surtout là pour illustrer les possibilités de la fonction ' "RWCheckBit", ' - La partie "Appels pour ensembles", et la procédure "SetModify", ' quant à elles, cherchent à montrer une utilisation possible ' des tables ainsi définies. Option Explicit 'Option Base 1 ' =========================================================================== ' Appels pour les ensembles ' ' 1 - Eléments d'un ensemble ' AddToSet ajoute un élément à l'ensemble ' RemFmSet retire un élément de l'ensemble ' IsInSet teste la présence d'un élément dans l'ensemble ' ' 2 - Modification d'ensembles ' SetClr remise à zéro d'un ensemble ' SetUni établit la réunion de deux ensembles ' SetInt établit l'intersection de deux ensembles ' SetSub établit la différence entre deux ensembles ' SetNot établit le complément d'une ensemble ' SetCopy Copie un ensemble ' ----------------------------------------------------------------------- Public Sub AddToSet(ByRef T() As Long, ByVal P As Byte) Call RWCheckBit(T, P, 1): End Sub ' ----------------------------------------------------------------------- Public Sub RemFmSet(ByRef T() As Long, ByVal P As Byte) Call RWCheckBit(T, P, 0): End Sub ' ----------------------------------------------------------------------- Public Function IsInSet(ByRef T() As Long, ByVal P As Byte) As Boolean IsInSet = RWCheckBit(T, P): End Function ' ----------------------------------------------------------------------- Public Sub SetClr(ByRef T() As Long) Call SetModify(T, T, T, 0): End Sub ' ----------------------------------------------------------------------- Public Sub SetUni(ByRef T1() As Long, T2() As Long, T3() As Long) Call SetModify(T1, T2, T3, 1): End Sub ' ----------------------------------------------------------------------- Public Sub SetInt(ByRef T1() As Long, T2() As Long, T3() As Long) Call SetModify(T1, T2, T3, 2): End Sub ' ----------------------------------------------------------------------- Public Sub SetSub(ByRef T1() As Long, T2() As Long, T3() As Long) Call SetModify(T1, T2, T3, 3): End Sub ' ----------------------------------------------------------------------- Public Sub SetNot(ByRef T1() As Long) Call SetModify(T1, T1, T1, 4): End Sub ' ----------------------------------------------------------------------- Public Sub SetCopy(ByRef T1() As Long, ByRef T3() As Long) Call SetModify(T1, T1, T3, 5): End Sub ' =========================================================================== ' Appels pour le positionnement des bits : ' ' BT teste le bit P ' BTS teste le bit P et le met à "True" ' BTR teste le bit P et le met à "False" ' BTC teste le bit P et le change ' ----------------------------------------------------------------------- Public Function BT(ByRef T() As Long, ByVal P As Byte) As Boolean BT = RWCheckBit(T, P): End Function ' ----------------------------------------------------------------------- Public Function BTS(ByRef T() As Long, ByVal P As Byte) As Boolean BTS = RWCheckBit(T, P, 1): End Function ' ----------------------------------------------------------------------- Public Function BTR(ByRef T() As Long, ByVal P As Byte) As Boolean BTR = RWCheckBit(T, P, 0): End Function ' ----------------------------------------------------------------------- Public Function BTC(ByRef T() As Long, ByVal P As Byte) As Boolean BTC = RWCheckBit(T, P, 2): End Function ' =========================================================================== Private Function RWCheckBit(ByRef T() As Long, _ ByVal P As Byte, _ Optional ByVal C As Byte = 3) As Boolean ' ----------------------------------------------------------------------- ' Positionne un bit dans une table de booléens. Dans tous les cas, ' utilisée comme fonction, retourne la valeur du bit correspondant, ' avant l'opération demandée. ' T Tableau formés de blocs de 4 octets (Long). En fait, afin ' d'éviter les problèmes de débordements sur le bit signe, ' seuls 31 des 32 octets disponibles sont utilisés ' P Position (ou n°) du bit dont la valeur doit être affectée ' C Commande optionnelle : ' 0 mettre à "False" ' 1 mettre à "True" ' 2 compléménté ' 3 (défaut) pas d'opération, lecture simple de ' la valeur du bit. ' =========================================================================== Const BkSize As Byte = 31 ' taille utile d'un bloc Dim BitMsk As Long ' masque correspondant à "P" Dim NumBk As Byte ' n° du bloc de 4 octets 'si P hors limites, selon "T", on sort. If P > ((UBound(T) - LBound(T) + 1) * BkSize) Then Exit Function Let NumBk = (P - 1) \ BkSize + LBound(T) ' masque relatif au bloc "NumBk", correspondant à la position "P" Let BitMsk = 2 ^ ((P - 1) Mod BkSize) RWCheckBit = (T(NumBk) And BitMsk) <> 0 Select Case C Case 0: Let T(NumBk) = T(NumBk) And Not BitMsk Case 1: Let T(NumBk) = T(NumBk) Or BitMsk Case 2: Let T(NumBk) = T(NumBk) Xor BitMsk End Select End Function ' =========================================================================== Private Sub SetModify(ByRef T1() As Long, _ ByRef T2() As Long, _ ByRef T3() As Long, _ ByVal C As Byte) ' ----------------------------------------------------------------------- ' Effectue une opération entre les ensembles T1 et T2 et met le résultat ' dans T3. Les déclarations de T1, T2 et T3 doivent être identiques. ' T1, T2 "ensembles" à traiter ' T3 "ensemble" résultat ' C commande : ' 0 remise à zéro ' 1 réunion ' 2 intersection ' 3 T1 - T2 ' 4 complément de T1 ' 5 copie ' =========================================================================== Const Cmp1 As Long = &H7FFFFFFF ' valeur pour complément à 1 Dim I As Byte ' indice de boucle For I = 1 To UBound(T1) Select Case C Case 0: Let T3(I) = 0 Case 1: Let T3(I) = T1(I) Or T2(I) Case 2: Let T3(I) = T1(I) And T2(I) Case 3: Let T3(I) = T1(I) And (T2(I) Xor Cmp1) Case 4: Let T1(I) = T1(I) Xor Cmp1 Case 5: Let T3(I) = T1(I) End Select Next I End Sub
ShadowMaster, tu as raison, "option Base 1" est, sommes toute, une contrainte inutile. J'ai donc modifié mon code dans ce sens. On n'est donc plus obligé de déclarer le tableau T(1..n).
Vlad2i, tu as raison, on peut simplifier. En fait, la première version positionnait le bit, en accord avec une valeur passée en argument, ce qui me faisait positionner le bit en 2 temps :
1 - RAZ ("and 0")
2 - positionnement ("or <valeur du bit")
A présent, ce n'est plus nécessaire, j'ai donc modifié le "case" en ce sens.
Toutefois, les valeurs de "C" ont été choisies de telle sorte que l'on peut toujours appeler la procédure, sans avoir testé au préalable la valeur que devra avoir le bit. il suffit de l'appeler ainsi :
RWCheckBit(T,P,abs(MonBooléen))
Quant à "Maxp", variable servant une seule fois (quel luxe !) je l'ai virée comme indiqué précédemment.
Merci beaucoup pour vos remarques qui me permettent de m'améliorer.
Par contre option base 1 moué ça peu avoir son utilité mais bon, pas indispensable, on peu declarer son tableau comme ça:
Dim T (1 to 5) as ...
J'écivais en même temps que toi ! lol !
Tu as raison : Je pourrais commencer par "virer" la variable "MaxP", par exemple. Enfin ! je ferai mieux (enfin... peut-être... :) ) la prochaine fois (l'espoir fait vivre, dit-on).
Encore merci à tous.
Option Explicit est ici sans grande importance. Je la mets systématiquement car elle force à déclarer "explicitement" doute variable. Si on omet d'en déclarer une, cela provoque une erreur à la compilation. Je trouve simplement que c'est une bonne précaution, pour une bonne habitude.
Option Base 1, par contre est importante dans ce code. Elle fixe l'indice inférieur par défaut d'un tableau. Sans cette option, la valeur infèrieure d'indice pour un tableau est 0.
Dans ce cas :
dim T(5) as... (ce que tu veux...) correspondrait au tableau T(0), T(1), T(2), T(3), T(4).
avec option base 1
dim T(5) as... (ce que tu veux...) correspond au tableau T(1), T(2), T(3), T(4), T(5).
or "Ubound" renvoie, non pas une taille, mais l'indice le plus élevé de la dimension demandée (la première, par défaut, dans ce code). De même "Lbound" retourne l'indice inférieur.
Moralité : si on prend l'instruction
Let MaxP=Ubound(T)*BkSize
celle-ci suppose que le premier élément de T est T(1).
On peut s'affranchir de l'"option base" en la remplaçant par :
Let MaxP=(Ubound(T)-Lbound(T)+1)*BkSize
Les autres instructions seraient à modifier dans le même ordre d'idée : là où on adresse T(n), par exemple, il faudrait adresser T(Lbound(T)+n-1) et ainsi de suite.
Il me semblait donc plus "léger" (bon !) de fixer l'option base (plus pour dire que je la fixais, d'ailleurs, ce que tu as fort bien vu, que pour la fixer à "1" proprement dit) et d'avoir un code un peu moins lourd.
Pour ce qui est de l'envoi réseau, ce n'est pas vraiment un domaine que je pratique. Si tu veux, tu peux m'indiquer souci en me contactant directement. Pas la peine de développer trop, dans un premier temps, juste histoire de me faire une idée sur le problème.
Espérant avoir apporté une petite contribution, je vous remercie pour l'intérêt que vous y portez.
Option Base 1 définit le premier élément d'un tableau à 1 (au lieu de 0)
Option Explicit oblige à déclarer les variables (au lieu de les supposer en variant)
Valà
Sinon un bon code, bien que l'on doit pouvoir faire plus léger qd meme :)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.