Enumération et Set Of
Enumération
Ressources sur les énumérations:
Déclaration d'une énumération
type MonthType = (January, February, March, April, May, June, July, August, September, October, November, December); // exemple d'utilisation var Month : MonthType; ... Month := January; // Equivalent a Month := TMonthType(0);
Ord
La function Ord permet de connaitre la valeur ordinale d'une valeur énumérée.
Exempe :
ord(January) = 0 ord(December) = 11
On peut modifier l'ordinale a la déclaration exemples :
type TMonthType = (January=1, February, March, April,May, June, July, August, September, October, November, December); type TMonthType = (January=1, FirstMonth=1,February=2, SecondMonth=2...); type TMonthType = (January=1, February, May=5,June, July);
Dans le dernier cas ord(January)
=1, ord(February)
=2, ord(May)
=5,ord(June)
=6, ord(July)
=7
Succ et Pred
succ(January) => February...
High et Low
Retourne respectivement la plus grande valeur (December) ou la plus petite valeur (January)
Exemples de codes
Parcourir un ensemble
for i := Ord(Low(TMonthType)) to Ord(High(TMonthType)) do begin x:= GetEnumName(TypeInfo(TMonthType), Ord(i)); end;
var vHandlerType: TDragManagerHandlerType; begin for vHandlerType := Low(TDragManagerHandlerTypee) to High(TDragManagerHandlerType) do FreeThenNil(FDragManHandlers[vHandlerType]); end;
Passer d'un Type énuméré a un ordinale et réciproquement
var vWS: integer; begin vWS := ord(wsFullScreen); //-> 4 WindowState:=TWindowState(vWS); end;
Set Of
Ressources sur les Set Of:
Déclaration d'une énumération + Set Of
type TMonth = (January, February, March, April, May, June, July, August, September, October, November, December); TMonths = set of TMonth;
In
on peut tester si un membre fait parti d'un SetOf avec l'operateur IN.
Months: TMonths ... if January in Months then...
Opérateur * pour verifier plusieurs membres du Set
if [csLoading,csDestroying,csDesigning]*ComponentState=[] then ...
Include / Exclude
Include (FComponentState,csUpdating); ... Exclude(FComponentState,csUpdating);
Comprendre les sets
Comment sont ils stocké en mémoire ?
D’après ce que j'ai compris les Sets sont en fait un masque de bits dont la longueur est égal au nombre d’élément dans l'ensemble de base (voir l'exemple ci dessous)
Le Set serait représenté par un Longint
pour les ensembles de moins de 32 éléments.
Et sur 32 Octets pour les ensembles de plus de 32 éléments.
Ce qui nous ferais un nombre de 256 éléments maximum (Set Of Byte = OK / Set Of Word = Error)…
Donc cela implique qu'il n'est pas possible de connaitre facilement le nombre d’éléments dans un Set, il n'existe pas de length(Set) ou autre.
Un high(Set)
sera égale a un high(Elements)
Exemple:
avec l'ensemble TTest = (b1,b2,b3,b4)
soit 4 éléments
Le Set of TTests = set of TTest
sera représenté par 4 bits d'un longint
Donc vTests :=[b1,b4]
sera representé par 1001
Donc vTests :=[b2,b3]
sera representé par 0110
Donc vTests :=[]
sera representé par 0000
Démo
Petit programme de démo:
program project1; uses sysutils; type TBit = (b0, b1, b2, b3, b4, b5, b6, b7); TBits = set of TBit; var vS: string; vBits: TBits; pI: pinteger; begin vBits := []; //(00000000...) pI := @vBits; // on "convertit" le Set en Integer writeln(IntToStr(pI^)); // -> 0 vBits := [b0]; //(10000000...) writeln(IntToStr(pI^)); // -> 1 vBits := [b1]; //(01000000...) writeln(IntToStr(pI^)); // -> 2 vBits := [b0, b1]; //(11000000...) writeln(IntToStr(pI^)); // -> 3 vBits := [b0, b7]; //(10000001...) writeln(IntToStr(pI^)); // -> 129 end.
Passer d'un Integer en Set of
Tout se passe dans la procedure IntAsSet
ci-dessous…
program project2; uses sysutils; type TBit = (b0, b1, b2, b3, b4, b5, b6, b7); TBits = set of TBit; var vS: string; vBits: TBits; pI: pinteger; procedure test(ABits: TBits); var //vBit: TBit; vI: integer; begin for vI := Ord(low(TBit)) to Ord(high(TBit)) do begin if TBit(vI) in ABits then writeln(IntToStr(vI) + ' = 1') else writeln(IntToStr(vI) + ' = 0'); end; end; procedure IntAsSet(AInt: integer; PSet: pointer); var pI: pInteger; begin pI := PSet; pI^ := Aint; end; begin vBits := []; //(00000000...) IntAsSet(255, @vBits); test(vBits); ReadLn(vS); end.