Transtyper (caster) ensemble (set of) [Résolu]

Signaler
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
-
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
-
Salut tout le monde,
une petite question me trotte dans la tete.
Est il possible de transtyper un set of QuelqueChose en entier ?
Parce que je me dis qu'il est bien possible que le compilateur stock ca sous forme de bits
Si j'ai
TX = (x1, x2, x3);
TXs = set of TX;
il fait surement :
[x1, x2] : 011
[x1, x3] : 101
[x1, x2, x3] : 111
[] : 000

qu'en pensez vous?
A voir également:

10 réponses

Messages postés
702
Date d'inscription
vendredi 21 mars 2003
Statut
Membre
Dernière intervention
1 octobre 2009
4
Salut, m'y revoilà !




type

  TSetInt = (s1, s2, s3);
  TSetInts = set of TSetInt;

procedure TForm1.FormCreate(Sender: TObject);
var
  T: TSetInts;
  resu: byte; // ou Word ou DWord
begin
  T : = [s1];
  resu := byte(T) ;  // pas d'erreur du compilateur
  T : = [s2];
  resu := byte(T);
  T := [s3];
  resu := byte(T);
  T := [s1, s2];
  resu := byte([s1]); // là : erreur de transtypage !
end ;






(avec D7)

Ken@vo




<hr size ="2" width="100%" />



Code, Code, Codec !
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
7
Ok, merci Kenavo :)

pour resumer :

type
  TSetInt = (s1, s2, s3);
  TSetInts = set of TSetInt;
const
  TMax = [s1..s3];
  TMid: TSetInts = [s2];
var
  T: TSetInts;
  R: integer;
begin
  T := [s1, s3];

  R := byte(T);    // pour  1..8  éléments dans l'enum
  R := Word(T);    //  "    9..16   "
  R := Cardinal(T);//  "   17..32   "

  R := Byte(T);        // variable du type du set : OK
  R := Byte([s1, s3]); // pas possible si passage direct du set
  R := Byte(TMax);     // pas possible si constante non typée
  R := Byte(TMid);     // constante typée : OK
end;
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
37
type
  TSetInt = (sA,sB,sC);
  TSetInts = set of TSetInt;

var
  SI : TSetInts;

function ToBinStr(const Buffer; const BufferSize : integer) : string;
var
  pB : ^byte;
  pR : PChar;
  N  : integer;
const
  BC : array[boolean] of char = '01';
begin
  pB := @Buffer;
  inc(pB, BufferSize-1);
  SetLength(result, BufferSize shl 3);
  pR := PChar(Result);
  for N := 0 to BufferSize-1 do
  begin
    pR[0] := BC[ (pB^ and $80) = $80 ];
    pR[1] := BC[ (pB^ and $40) = $40 ];
    pR[2] := BC[ (pB^ and $20) = $20 ];
    pR[3] := BC[ (pB^ and $10) = $10 ];
    pR[4] := BC[ (pB^ and $08) = $08 ];
    pR[5] := BC[ (pB^ and $04) = $04 ];
    pR[6] := BC[ (pB^ and $02) = $02 ];
    pR[7] := BC[ (pB^ and $01) = $01 ];
    dec(pB);
    inc(pR,8);
  end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  SI := [];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> []');
  SI := [sA];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sA]');
  SI := [sB];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sB]');
  SI := [sC];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sC]');
  SI := [sA,sB];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sA,sB]');
  SI := [sA,sC];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sA,sC]');
  SI := [sB,sC];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sB,sC]');
  SI := [sA, sB, sC];
  ListBox1.Items.Add(ToBinStr(SI, SizeOf(TSetInt))+' ==> [sA,sB,sC]');
end;





affichera :
00000000 ==> []
00000001 ==> [sA]
00000010 ==> [sB]
00000100 ==> [sC]
00000011 ==> [sA, sB]
00000101 ==> [sA, sC]
00000110 ==> [sB, sC]
00000111 ==> [sA, sB, sC]

donc :
sA = 1
sB = 2
sC = 4

si on fait :
  TSetInt = (
    sA = 1,
    sB = 2,
    sC = 3
  );

alors :
00000000 ==> []
00000010 ==> [sA]
00000100 ==> [sB]
00001000 ==> [sC]
00000110 ==> [sA,sB]
00001010 ==> [sA,sC]
00001100 ==> [sB,sC]
00001110 ==> [sA,sB,sC]

donc:
sA = $02
sB = $04
sC = $08

<hr size="2" width="100%" />
si on fait :

  TSetInt = (
    sA = $FF,
    sB = sA-1,
    sC = sB-1
  );

alors :
00000000 ==> []
10000000 ==> [sA]
01000000 ==> [sB]
00100000 ==> [sC]
11000000 ==> [sA,sB]
10100000 ==> [sA,sC]
01100000 ==> [sB,sC]
11100000 ==> [sA,sB,sC]

donc:
sA = $80

sB = $40

sC = $20

en gros, ça revient a faire ceci :
const
  sA = $01;
  sB = $02;
  sC = $04;
  sAB = sA or sB;
  sAC = sA or sC;
  sBC = sB or sC;
  sABC = sA or sB or sC;

donc oui les sets stocke dans des bits.

par contre avec les set of char ou set of byte, ça devient vite illisible, puisqu'il stocke le set sur 32 octets soit 256bits (8x32bits)

set avec moins de 8 valeurs =   8 bits  (byte)
entre 8 et 16 valeurs       =  16 bits  (word)
entre 16 et 32 valeurs      =  32 bits  (doubleword)
entre 32 et 64 valeurs      =  64 bits  (2x doubleword)
entre 64 et 128 valeurs     = 128 bits  (4x doubleword)
entre 128 et 256 valeurs    = 256 bits  (8x doubleword)

on comprend pourquoi il limite le nombre de valeurs a 256!

<hr size="2" width="100%" />
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
37
oops

on comprend pourquoi il limite le nombre de valeurs a 256!

puisque le suivant serait :

entre 256 et 65 536 valeurs    = 65 536 bits  (2 048x doubleword)
puis

entre 65 536 et  valeurs 4 294 967 296 = 4 294 967 296 bits  (134 217 728x doubleword)
512Mo!

<hr size="2" width="100%" />
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
37
et aussi :

if sValeur in sSetOfValeur  then ..

sSetOfValeur = sSetOfValeur + [sValeur];

sSetOfValeur = sSetOfValeur - [sValeur];

et equivalent a :

if (vValeur and vVariable) <> 0  then .. (1101 and 0001 = 0001)
vVariable vVariable or vValeur  (1100 or 0001 1101)
vVariable vVariable xor vValeur (1101 xor 0001 1100)

exemple :

type
  TlwAnchors = LongWord;

const
  clwALeft   = $01;
  clwATop    = $02;
  clwARight  = $04;
  clwABottom = $08;

var
  lwAnchors = Tlwanchors;

ancrer a gauche seulement :
  lwAnchors = clwALeft;
    -> = 0001

ancrer a gauche et a droite :
  lwAnchors = clwALeft or clwARight;    -> 0001 or 0100 0101

ajouter l'ancrage a droite et en bas :
  lwAnchors = lwAnchors or (clwARight or clwABottom);    -> 0101 or (0100 or 1000) 0101 or 1100 = 1101

supprimer l'ancrage a gauche et en bas :
  lwAnchors = lwAnchors xor (clwATop or clwABottom);    -> 1101 xor (0010 or 1000) 1101 xor 1010 =  0101

est ancré a gauche ? :
  bool = (lwAnchors and clwALeft) <> 0;

est ancré en bas et a droite ? :
  bool = (lwAnchors and (clwARight or clwABottom)) <> 0;

     

<hr size="2" width="100%" />
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
7
c'est l'option que j'ai choisie, sauf que j'utilise un cardinal.
ca me donne un truc du genre:

TSetInt = (s1, s2, s3);
TSetInts = set of TSetInt;

function SetIntsToInt(const ASet: TSetInts): Cardinal;
var
  i: TSetInt;
begin
  assert(High(TSetInt) < sizeOf(Cardinal)*8); //on s'assure que toutes les valeurs peuvent etre contenues dans le cardinal
  Result := 0;
  for i := Low(TSetInt) to High(TSetInt) do
    if i in ASet then
      Inc(Result, 1 shl Ord(i));
end;
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
7
... mais ca m'aurait arranger si je pouvai le caster directement
Messages postés
702
Date d'inscription
vendredi 21 mars 2003
Statut
Membre
Dernière intervention
1 octobre 2009
4
Salut,

As-tu essayé :

Pour un ensemble de 8 élément max :
 



  resu := byte(Aset);  // simple transtypage à la c..




Pour un ensemble de 16 élément max :

 



  resu := Word(Aset);




Pour un ensemble de 32 élément max :

 



  resu := DWord(Aset);





Ken@vo




<hr size ="2" width="100%" />



Code, Code, Codec !
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
7
oui j'ai essayé, il me met "transtypage incorrect"

d'où ce post en fait ;)
Messages postés
702
Date d'inscription
vendredi 21 mars 2003
Statut
Membre
Dernière intervention
1 octobre 2009
4
Étrange !

Je suis sûr d'avoir utilisé un tel transtypage (avec Delphi7). Je vérifierai ...

Ken@vo




<hr size="2" width="100%" />



Code, Code, Codec !