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

Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
- - Dernière réponse : Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
- 21 sept. 2008 à 13:17
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?
Afficher la suite 

Votre réponse

10 réponses

Meilleure réponse
Messages postés
759
Date d'inscription
vendredi 21 mars 2003
Dernière intervention
1 octobre 2009
3
Merci
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 !

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de cs_Kenavo
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
3
Merci
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;

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de Guillemouze
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
0
Merci
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%" />
Commenter la réponse de f0xi
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
0
Merci
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%" />
Commenter la réponse de f0xi
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
0
Merci
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%" />
Commenter la réponse de f0xi
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
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;
Commenter la réponse de Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
... mais ca m'aurait arranger si je pouvai le caster directement
Commenter la réponse de Guillemouze
Messages postés
759
Date d'inscription
vendredi 21 mars 2003
Dernière intervention
1 octobre 2009
0
Merci
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 !
Commenter la réponse de cs_Kenavo
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
oui j'ai essayé, il me met "transtypage incorrect"

d'où ce post en fait ;)
Commenter la réponse de Guillemouze
Messages postés
759
Date d'inscription
vendredi 21 mars 2003
Dernière intervention
1 octobre 2009
0
Merci
É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 !
Commenter la réponse de cs_Kenavo

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.