![]() |
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)^;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:49 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