![]() |
Speicherung von Sets... ?!?
Wie speichert man Sets (z.b. als wert oder ka wie)? :roll:
Und wie speichert das Delphi im Speicher??? Ich hab folgendes:
Delphi-Quellcode:
Wenn ich nun so ein set habe: [wdMonday, wdWednesday, wdFriday ]
Type
TWeekday = ( wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday ); TWeekdays = Set Of TWeekday; muss das doch wie gespeichert sein, nur wie? :gruebel: Bye |
Re: Speicherung von Sets... ?!?
moin,
meines Wissens sind Sets ordinale Typen, d.h. jedes Element entspricht einer Zahl. Deswegen kann man sie auch in Case-Abfragen verwenden. |
Re: Speicherung von Sets... ?!?
Ja, Sets gibt es nur für ordinale Typen. Deswegen könnte man auch die Ordinalwerte der im Set vorhandenen Elemente in einer Datei speichern un diese auch wieder laden.
In deinem Beispiel entspricht wdMonday dem Wert 0, wdTuesday entspricht 2, ..., wdSunday entspricht 6. Man könnte damit sogar rechenen:
Delphi-Quellcode:
MfG
var test1: TWeekday;
begin test1:= wdTuesday; test1:= TWeekday(Ord(test1) + Ord(wdTuesday)+ Ord(wdFriday)); //test1 ist jetzt wdSunday end; Binärbaum |
Re: Speicherung von Sets... ?!?
Ich glaun ich habs raus...
cmd1 = TButton txt1 = TMemo
Delphi-Quellcode:
Ergebniss:
Procedure TfrmMain.cmd1Click(Sender: TObject);
Function GetValue( Const WD: TQWeekdays ): Cardinal; Begin Case SizeOf( wd ) Of 1: Result := Cardinal( (@wd)^ ) And $000000ff; 2: Result := Cardinal( (@wd)^ ) And $0000ffff; 3: Result := Cardinal( (@wd)^ ) And $00ffffff; 4: Result := Cardinal( (@wd)^ ) And $ffffffff; Else Result := 0; End; End; Function InfoStr( Const WD: TQWeekdays ): String; Begin Result := #9'Size:'#9 + IntToStr( SizeOf( WD ) ) + #13#10 + #9'Value:'#9 + IntToStr( GetValue( WD ) ); End; Begin txt1.Clear; txt1.Lines.Append( '[ ]'#13#10 + InfoStr( [ ] ) ); txt1.Lines.Append( '[ wdMonday ]'#13#10 + InfoStr( [ wdMonday ] ) ); txt1.Lines.Append( '[ wdTuesday ]'#13#10 + InfoStr( [ wdTuesday ] ) ); txt1.Lines.Append( '[ wdWednesday ]'#13#10 + InfoStr( [ wdWednesday ] ) ); txt1.Lines.Append( '[ wdThursday ]'#13#10 + InfoStr( [ wdThursday ] ) ); txt1.Lines.Append( '[ wdFriday ]'#13#10 + InfoStr( [ wdFriday ] ) ); txt1.Lines.Append( '[ wdSaturday ]'#13#10 + InfoStr( [ wdSaturday ] ) ); txt1.Lines.Append( '[ wdSunday ]'#13#10 + InfoStr( [ wdSunday ] ) ); txt1.Lines.Append( #13#10#13#10 ); txt1.Lines.Append( '[ wdMonday, wdTuesday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday ] ) ); txt1.Lines.Append( '[ wdMonday, wdTuesday, wdWednesday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday , wdWednesday ] ) ); txt1.Lines.Append( '[ wdMonday, wdTuesday, wdWednesday, wdThursday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday, wdWednesday, wdThursday ] ) ); txt1.Lines.Append( '[ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday ] ) ); txt1.Lines.Append( '[ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday ] ) ); txt1.Lines.Append( '[ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday ]'#13#10 + InfoStr( [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday ] ) ); End;
Code:
Scheinbar macht es Delphi so..
[ ]
Size: 1 Value: 0 [ wdMonday ] Size: 1 Value: 1 [ wdTuesday ] Size: 1 Value: 2 [ wdWednesday ] Size: 1 Value: 4 [ wdThursday ] Size: 1 Value: 8 [ wdFriday ] Size: 1 Value: 16 [ wdSaturday ] Size: 1 Value: 32 [ wdSunday ] Size: 1 Value: 64 [ wdMonday, wdTuesday ] Size: 1 Value: 3 [ wdMonday, wdTuesday, wdWednesday ] Size: 1 Value: 7 [ wdMonday, wdTuesday, wdWednesday, wdThursday ] Size: 1 Value: 15 [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday ] Size: 1 Value: 31 [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday ] Size: 1 Value: 63 [ wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday ] Size: 1 Value: 127 lieg ich da richtig? :gruebel: Dann könnt ich das eigendlich so spiechern oder? :duck: Bye Edit: Bei der Funktion GetValue Greif ich atm auf speicher zu der mir nix angeht, jedenfalls wenn Size <> 4 ist... Könnte ich da Probleme bekommen? :gruebel: |
Re: Speicherung von Sets... ?!?
Ja, ordinal geht es prima, aber am schönsten mit strings. Die unit TypeInfo hat zwei funktionen die das konvertieren von set-properties beherrschen. Leider ist das auf auf properties spezialisiert. Ich hatte das mal entspezialisiert, sodass es mit normalen typeInfos geht:
Delphi-Quellcode:
Damit kann man super leicht konverieren:
uses typInfo, RTLConsts;
... function SetToStr(SetTypeInfo:PTypeInfo;value:integer;Brackets:boolean=true):string; var S: TIntSet; TypeInfo: PTypeInfo; compTypeDate: PTypeData; I: Integer; begin Result := ''; Integer(S) := Value; TypeInfo := GetTypeData(SetTypeInfo)^.CompType^; compTypeDate := GetTypeData(TypeInfo); for I := compTypeDate.MinValue to compTypeDate.MaxValue do if I in s then begin if Result <> '' then Result := Result + ','; Result := Result + GetEnumName(TypeInfo, I); end; if Brackets then Result := '[' + Result + ']'; end; function StrToSet(SetTypeInfo:PTypeInfo; const Value: string): Integer; var P: PChar; EnumName: string; EnumValue: Longint; EnumInfo: PTypeInfo; // grab the next enum name function NextWord(var P: PChar): string; var i: Integer; begin i := 0; // scan til whitespace while not (P[i] in [',', ' ', #0,']']) do Inc(i); SetString(Result, P, i); // skip whitespace while P[i] in [',', ' ',']'] do Inc(i); Inc(P, i); end; begin Result := 0; if Value = '' then Exit; P := PChar(Value); // skip leading bracket and whitespace while P^ in ['[',' '] do Inc(P); EnumInfo := GetTypeData(SetTypeInfo)^.CompType^; EnumName := NextWord(P); while EnumName <> '' do begin EnumValue := GetEnumValue(EnumInfo, EnumName); if EnumValue < 0 then raise EPropertyConvertError.CreateResFmt(@SInvalidPropertyElement, [EnumName]); Include(TIntegerSet(Result), EnumValue); EnumName := NextWord(P); end; end;
Delphi-Quellcode:
Entsprechend leicht dürfte das speichern in eine datei sein -> stringStream oder so.
type
T8BitSet = set of (bit_0, bit_1, bit_2, bit_3, bit_4, bit_5, bit_6, bit_7); ... var Bits:T8BitSet; s:string; begin Bits := [bit_2, bit_4, bit_7]; ... s := setToStr(typeInfo(T8BitSet), PInteger(@Bits)^, true); .. PInteger(@Bits)^ := strToSet(typeInfo(T8BitSet), s); end; Und wenn es hier nicht gebraucht wird, dann sicher später von jemand anderem! //edit: PS:@Kedariodakon: Du hast quasi gerade entdeckt, dass jeder eintrag in einem set einem bit entspricht...was auch logisch und effizient ist. //edit2: blöde pointer |
Re: Speicherung von Sets... ?!?
öhm sieht ja mega kompliziert aus :nerd:
Ich glaub ich mach das so wie es auch delphi macht... Auslesen ist ja nicht soooo schwer, wie oben in meinem Test bewiesen, aber beim Speichern weiß ich noch nicht wie ich das mach... :coder2: Kann man einfach für den Pointer der SetVariable Speicher hollen mit GetMem ??? Oder ist die Variable von sich aus schon so groß wie das max Set? :gruebel: Bye |
Re: Speicherung von Sets... ?!?
Zitat:
das findest du komplzier? Das musst du mir erklären? Ich würde eher sagen dein gelöt von oben ist kompliziert, bzw. redundant. Übrigens ist das die delphi-lösung, die auch das DFM-Streaming-system verwendet! PS: Die beiden funktionen oben SetToStr und StrToSet sind komplett implementiert und können ohne jegliches verständnis benutzt werden |
Re: Speicherung von Sets... ?!?
:roll:
Zitat:
Ich find es in der hinsicht kompliziert, dass ich zum speichern eines Sets von Wochentagen auf sowas "komplizertes" soll/muß/kann... Warum z.b. muß ich zum speichern/laden eines Sets in der RTTI rumwusseln, wenn jedes Element eines Types ein Bit darstellt :gruebel: Aber nichts für ungut, ich werd mich mit dem Codeschnippsel heut abend mal beschäftigen, vielleicht lern ich was daraus :angel2: Bye Edit: DFM-Streaming-system = Das speichern/laden von Published OBjectPropertys als String. Richtig? |
Re: Speicherung von Sets... ?!?
Zitat:
@DFM-Streaming: DFM dateien? schon mal gesehen :mrgreen: ...da werdenn auch sets gespeichert, die du zB. im OI eingestellt hast. |
Re: Speicherung von Sets... ?!?
PS:
wenn dir das egal ist und du es dennoch binär speichern willst, dann kannst du es so als integer machen:
Delphi-Quellcode:
i := PInteger(@Bits)^;
|
Re: Speicherung von Sets... ?!?
Zitat:
Aber wie du schon sagtest, bei wochentagen ist die chance nicht sehr hoch, dass da einer dazukommt, bzw gestrichen wird. Und falls doch muß das Programm eh wieder neu kompiliert werden, weil wenn nicht es bei einer BÜcherverbre...*hüsst* Programmverbrennung vernichtet würde :zwinker: Zitat:
Zitat:
|
Re: Speicherung von Sets... ?!?
Kleiner Chrash-Kurs über Mengen (Sets):
* ein Set kann maximal 256 Elemente speichern deshalb ist z.B. ein Set of Integer nicht möglich. Ein Set benötigt folgenden Speicherplatz
Code:
Ob ein Element in einem Set enthalten ist oder nicht, wird bitcodiert.
1 bis 8 Elemente => 1 Byte
9 bis 16 Elemente => 2 Byte 17 bis 32 Elemente => 4 Byte 33 bis 39 Elemente => 5 Byte 40 bis 48 Elemente => 6 Byte 49 bis 56 Elemente => 7 Byte 57 bis 64 Elemente => 8 Byte 65 bis 72 Elemente => 9 Byte ... bis 256 Elemente => 16 Byte Das 1. Element entspricht dem niederwertigsten Bit (LSB). Das Casten eines Set in einen Integer und zurück ist nur bis max. 32 Elemente möglich. |
Re: Speicherung von Sets... ?!?
Zitat:
Delphi-Quellcode:
Heißt das, daß die VCL generell auf 32 bit sets beschränkt ist?
function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean = False): string;
|
Re: Speicherung von Sets... ?!?
Also mann kann auch locker ein Set nach Array[0..7] of Byte / Array[0..3] of Word ... casten, dann hat man die vollen 256 Werte zur Verfügung
Derzeit aber ich ja an ein paar kleinen Units, wo es auch schon fertige Typen gibt, welche das umwandeln/casten solcher typen in andere und zurück vereinfacht... ich weiß aber noch nicht wann ich genau fertig bin |
Re: Speicherung von Sets... ?!?
Zitat:
Zitat:
Aber das hier Casten geht wusste ich noch nicht, gut zu wissen, dann hätte sich mein Wochentag speicherproblem gelöst :wink: Dann erstmal danke für des Résumé :thumb: Aber eine Frage ist immer noch offen, ist die SetVariable von sich aus schon so groß wie das volle Set einnimmt? :duck: Bye |
Re: Speicherung von Sets... ?!?
Zitat:
Delphi-Quellcode:
Und in der Unit TypInfo wird so damit gearbeitet:
// aus der Unit SysUtils kopiert:
// Ein Set mit 32 Elementen (0..31) TIntegerSet = set of 0..SizeOf(Integer) * 8 - 1;
Delphi-Quellcode:
Das gilt bei Delphi 5; ob bei höheren Version mehr als 32 Elemente möglich kann ich nicht sagen.
function GetSetProp(Instance: TObject; PropInfo: PPropInfo;
Brackets: Boolean): string; var S: TIntegerSet; // 4 Bytes ... begin Integer(S) := GetOrdProp(Instance, PropInfo); ... for I := 0 to SizeOf(Integer) * 8 - 1 do // <= Schleife von 0 bis 31 |
Re: Speicherung von Sets... ?!?
Zitat:
|
Re: Speicherung von Sets... ?!?
Das mein ich jetzt nicht ^^
Angenommen ich habe ein typ TTest mit 32 Elementen, und bau daraus ein set namens TTests, nun erstelle ich eine Variable
Delphi-Quellcode:
.
var Settest: TTests;
nun mach ich folgendes:
Delphi-Quellcode:
hat nun Settest eine größe von 4 Byte oder von 1 ?
Settest := [];
Bye |
Re: Speicherung von Sets... ?!?
Das set ist immer nur so groß, wie nötig
Größe in Byte = Aufrunden(Elemente / 8) Aber es gibt auch eine Möglichkeit dem Set eine gewisse größe aufzuzwingen, entweder per Compilerschalter {$X-} / {$X+} oder {$X1}, {$X2}, {$X4} aber was für das X hinkomm , fällt mir gerade nicht ein (aber dafür ist ja die OH da ^^) oder man gibt einfach dem letzten element eine Position ... = Set of (aaa, bbb, ccc, ddd=31); // hier ist dann das Set 32 Bit/4 Byte groß PS: auf diese Weise kann man auch allen elementen selber nummern verzeilen :zwinker: |
Re: Speicherung von Sets... ?!?
Zitat:
|
Re: Speicherung von Sets... ?!?
Ich hab ein kleines Problem mit TypInfo.GetSetProp.
und zwar verreckt dieses mit einer Exception, Zitat:
dieses geht ohne Probleme:
Delphi-Quellcode:
hier kommt die Exception:
TXMLNodeType = (xtInstruction, xtTypedef, xtElement, xtCData, xtComment, xtUnknown);
TXMLNodeTypes = Set of TXMLNodeType; TXMLNodeType = (xtInstruction, xtTypedef, xtElement, xtCData, xtComment, xtUnknown=5); TXMLNodeTypes = Set of TXMLNodeType;
Delphi-Quellcode:
TXMLNodeType = (xtInstruction, xtTypedef, xtElement, xtCData, xtComment, xtUnknown=6);
TXMLNodeTypes = Set of TXMLNodeType; TXMLNodeType = (xtInstruction, xtTypedef, xtElement, xtCData, xtComment, xtUnknown=31); TXMLNodeTypes = Set of TXMLNodeType; |
Re: Speicherung von Sets... ?!?
Zitat:
die Grösse ist ja zur Compile Time bekannt, daher ist ein Set of 1..5 nur 1 Byte, ein Set of Byte 32 Byte gross. @shmia: 256 / 8 = 32 ! Gruss Reinhard |
Re: Speicherung von Sets... ?!?
Zitat:
{$MinimumEnumSize} = 4, dann ist auch ein Set mit nur 1 Wert drin auch 4 Byte. zu meinem Problem: ich versuch die TypInfo grad zu zerlegen und der Fehler liegt vermutlich in der Internen TypInfo.InternalGetPropInfo (k.A. eventuell Stack zersört), aber abStürzen tut es dann am Ende (end;) von FindPropInfo. [add] ach ja ... Delphi2009 (probier heut abend mal eine ältere Version) [edit] TypInfo.InternalGetPropInfo isses doch nicht ... weiter geht die Suche im anderen TypInfo.GetSetProp :x |
Re: Speicherung von Sets... ?!?
so, hab die letzte Stunde versucht die TypInfo zu debuggen ...
Delphi-Quellcode:
bei Sets mit freien Stellen ist CompType nicht vorhanden (= nil) :shock:
TTypeData > tkSet: (CompType: PPTypeInfo));
in der TypInfo.SetToString wird dieses hier
Delphi-Quellcode:
aufgerufen, liefert nil und da es daraufhin ungeprüft dereferenziert wird,
GetTypeData(PropInfo^.PropType^)^.CompType
Delphi-Quellcode:
knallt es.
TypeInfo := GetTypeData(PropInfo^.PropType^)^.CompType^;
die Frage ist nur, warum gibt es, bei sowas
Code:
, keine PPTypeInfo mehr? :?
TXMLNodeType = (xtInstruction, xtTypedef, xtElement, xtCData, xtComment, xtUnknown[color=#ff0000][b]=6[/b][/color]);
TXMLNodeTypes = Set of TXMLNodeType; [edit=alzaimar]'freuen' -> 'freien' auf Bitten des Beitragverfassers. Mfg, alzaimar[/edit] |
Re: Speicherung von Sets... ?!?
![]() hat da jemand 'ne Idee, wie man das elegant umgehen kann, bzw. ob doch irgendwie die TypeInfo herzubekommen ist, wenn man einen Set mit leeren Stellen hat? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz