![]() |
Integer in Set laden
Ich habe diese Deklarationen
Delphi-Quellcode:
In einer Procedure lade ich einen Integerwert aus einer Datei der zum Beispiel 57 sein kann in eine Variable NiveauInt.
type
TNiveau = (nA = 1, nB = 2, nC = 4, nC = 8, nD = 16, nE = 32); TNiveauSet = set of TNiveau; Mit sowas hier gucke ich, welches Niveau im Set enthalten ist (insgesamt 6x)
Delphi-Quellcode:
Das Problem ist, dass ich die 57 nicht in die Variable NiveauInt geladen bekomme.
if TNiveau.nA in NiveauInt then
Include(NiveauSet, TNiveau.nA); Mein Versuch
Delphi-Quellcode:
Egal von welchem Typ NiveauInt ist, es klappt nicht. Was mache ich falsch?
NiveauInt := TNiveauSet(Byte(57));
|
AW: Integer in Set laden
Der höchste Wert im Set is 32. Damit benötigt das Set 33 Bit und passt nicht mehr in einen Integer - und schon gar nicht in ein Byte.
|
AW: Integer in Set laden
Habe ich hier einen Denkfehler? Int64 funktioniert auch nicht.
Das Problem ist, dass ich = 1, = 2, = 4 bis 32 angeben muss, da die Werte die von Außen kommen sonst nicht stimmen.
Delphi-Quellcode:
NiveauInt := TNiveauSet(StrToInt64Def(57, 0));
|
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Ist nur ein Tippfehler hier im Editor von mir. Da kommt schon ein String rein.
|
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Nimm das nC weg :P Es sind nur Tippfehler im Editor. Das ist so gesehen realer Code nur habe ich die Variablennamen abgeändert. Alle Namen der Deklarationen sind bei mir richtig.
Sowas würde der Compiler als aller erstes bemängeln. Aber es geht nur um diese Umwandlung. Es hakt nur an dieser einen Stelle
Delphi-Quellcode:
Die 57 kommt aus einer Textdatei.
NiveauInt := TNiveauSet(StrToInt64Def('57', 0));
Auch hiermit kommt der Umwandlungsfehler. Also ohne Zuweisungen der Zahlen.
Delphi-Quellcode:
Füge ich dann oben Byte() hinzu, funktioniert es. Aber ich brauche leider die Wert bis = 32.
TNiveau = (nA, nB, nC, nD, nE, nF);
Ich erkläre mal das Vorhaben. Ein externes Programm hat 6 Niveau-Stufen die man freischalten kann. Das Programm speichert das in folgenden Schritten: 1, 2, 4, 8, 16 und 32. Hat man alle 6 Stufen freigeschaltet, steht in der Konfigurationsdatei 63. Diese Zahl lese ich aus und möchte meine Datentypen oben damit korrekt füllen. Das mache ich mit den
Delphi-Quellcode:
-Abfragen.
in
|
AW: Integer in Set laden
Wenn solche Typ-Umwandlungen haken kann man gut mit varianten Records "herumspielen". In deinem Fall:
Code:
var
Niveau: case boolean of false: (Menge: TNiveauSet); true : (Int : int64) end |
AW: Integer in Set laden
Zitat:
Zitat:
Da deine Integerwerte nicht größer als 63 werden können, genügt ein Byte-Cast. Direkt auf den Integer casten geht nicht, da das Set nur ein Byte groß ist und somit beim Cast auf einen Integer die Größe nicht passt. |
AW: Integer in Set laden
Zitat:
Delphi-Quellcode:
type
TNiveau = (nA, nB, nC, nD, nE, nF); TNiveauSet = set of TNiveau; var Niveaus: TNiveauSet; NiveauZahl: Byte; begin Niveaus := TNiveauSet(Byte(StrToInt('57'))); NiveauZahl := Byte(Niveaus); end; |
AW: Integer in Set laden
Wenn ins Programm 57 eingelesen wird, wie ermittle ich dann welche Niveaus freigeschaltet wurden bei nur 6 Bit?
Das externe programm speichert Niveau 1 mit 1 ab, 2 mit 2, 3 mit 4, 4 mit 8, 5 mit 16 und 6 mit 32. |
AW: Integer in Set laden
Zitat:
Wenn Du wissen willst, ob Niveau 5 freigeschaltet ist, dann ist die Abfrage dazu
Code:
Hast Du meinen Quelltext mal ausprobiert?
nE in Niveaus
Vielleicht ist es so klarer:
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type TNiveau = (Niveau1, Niveau2, Niveau3, Niveau4, Niveau5, Niveau6); TNiveauSet = set of TNiveau; var Niveaus: TNiveauSet; NiveauZahl: Byte; begin Niveaus := TNiveauSet(Byte(StrToInt('57'))); NiveauZahl := Byte(Niveaus); if Niveau5 in Niveaus then WriteLn('Niveau 5 ist freigeschaltet'); end. |
AW: Integer in Set laden
Ich glaube du hast mich nicht verstanden.
Ich speichere gar nix ab. Ich lese nur aus. Das andere Programm speichert ab mit 1 2 4 8 16 32 und allen Kombinationen daraus. Da kann ich nix dran ändern. Und das muss ich auslesen. Und da das hier nicht funktioniert bin ich aufgeschmissen
Delphi-Quellcode:
TNiveau = (nA = 1, nB = 2, nC = 4, nD = 8, nE = 16, nF = 32);
TNiveauSet = set of TNiveau; NiveauInt := TNiveauSet(StrToInt64Def(<der wert der von draußen kommt>, 0)); |
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Zitat:
Code:
Da wird in der Variablen NiveauInt etwas gespeichert. Bei meinem Programm wird in der Variablen "Niveaus" ebenfalls etwas gespeichert.
NiveauInt := <irgendwas>
|
AW: Integer in Set laden
Dann verstehe ich euch tatsächlich nicht und verstehe auch grundsätzlich überhaupt nix mehr.
Wenn ich von Außen 57 lese dann bedeutet das Niveau 1, 4, 5 und 6 sind frei. 2 und 3 noch nicht. Wie gestaltet sich dann die Abfrage?
Delphi-Quellcode:
Aber da oben wird doch im Prinzip geprüft, ob die 1 in der 57 ist. Denn Element nB ist das zweite Element im Set mit dem Wert 1.
if TNiveau.nB in NiveauInt then // das hier dürfe niemals zutreffen, da Niveau 2 (B) nicht freigeschaltet ist.
Include(NiveauSet, TNiveau.nB); Aber eigentlich müsste ich 2 abfragen. Ok ich glaube das wars ich gebe auf. Ich brauche diese Zahlen weil ich sonst keine Ahnung habe wie ich prüfen kann was frei ist und was nicht. |
AW: Integer in Set laden
Ich kann mich nur wiederholen. Mein Programm leistet exakt das, was Du möchtest. Teste es doch bitte bitte bitte mal!
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type TNiveau = (Niveau1, Niveau2, Niveau3, Niveau4, Niveau5, Niveau6); TNiveauSet = set of TNiveau; var Niveaus: TNiveauSet; N: TNiveau; begin Niveaus := TNiveauSet(Byte(StrToInt('57'))); // Integer in das Set laden // Ausgabe welche Niveaus freigeschaltet sind for N:=Niveau1 to Niveau6 do begin if N in Niveaus then WriteLn(Format('Niveau %d ist freigeschaltet', [ord(N)+1])); end; ReadLn; end. |
AW: Integer in Set laden
Warum machst Du es nicht nach alter Väter Sitte
Delphi-Quellcode:
Gruß
funktion Bit0set(wert:byte)_boolean;
begin result:=((wert and 1) =1); end; funktion Bit1set(wert:byte):boolean; begin result:=((wert and 2) =2); end; usw. K-H |
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Zitat:
Delphi-Quellcode:
Gerne liefere ich das auch in Assembler...
program Project1;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; var Niveaus: Integer; i: Integer; N: Integer; begin Niveaus := StrToInt('57'); N := 1; for i := 1 to 6 do begin if N and Niveaus<>0 then WriteLn(Format('Niveau %d ist freigeschaltet', [i])); N := N * 2; end; ReadLn; end. |
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Zitat:
Ich hab bisher den Eindruck, daß der Einsatz eines Sets nicht eben intuitiv ist. Gruß K-H |
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
Hallo Dolly
gib nicht auf :-D. Die Vorschläge sind ja alle mehr als brauchbar. Hier noch ein paar Funktionen, welche nützlich sein könnten... allefaelle zählt alle möglichen Fälle (0..63) auf niv_in_n prüft, ob ein Niveau im "Fall" n enthalten ist niv_str wandelt ein Element in einen String um nivset_str wandelt eine Menge in einen String um
Delphi-Quellcode:
uses System.TypInfo;
type TNiveau = (nA, nB, nC, nD, nE, nF); TNiveauSet = set of TNiveau; function getNiveauSet( n : byte ) : TNiveauSet; begin (* alle fälle aufzählen: Result := []; if n and 1 = 1 then Result := Result + [nA]; if n and 2 = 2 then Result := Result + [nB]; if n and 4 = 4 then Result := Result + [nC]; if n and 8 = 8 then Result := Result + [nD]; if n and 16 = 16 then Result := Result + [nE]; if n and 32 = 32 then Result := Result + [nF]; *) // oder einfacher so: Result := TNiveauSet( n ); end; function niv_str( niv : TNiveau ) : string; begin Result := GetEnumName(typeinfo(TNiveau),ord(niv)); end; function nivset_str( nivset : TNiveauSet ) : string; var niv : TNiveau; begin Result := ''; for niv := nA to nF do if niv in nivset then Result := Result + niv_str( niv ) + ' '; end; function niv_in_n( niv : TNiveau; n : byte ) : boolean; begin Result := niv in getNiveauSet( n ); end; function fallnummer( n : byte ) : string; var nivset : TNiveauSet; begin nivset := getNiveauSet( n ); Result := nivset_str( nivset ); end; function allefaelle : string; var i: Integer; hs : string; begin hs := ''; for i := 0 to 63 do hs := hs + i.ToString + ' ' + fallnummer( i ) + #13#10; Result := hs; end; procedure TForm1.Button1Click(Sender: TObject); begin showmessage(allefaelle); end; |
AW: Integer in Set laden
In dem Augenblick in dem die Zahl in ein Set übertragen wurde, muss man gedanklich die Welt der Zahlen verlassen und in die Welt der Mengenlehre eintauchen. Hier wird nicht mehr mit Zahlen hantiert, sondern mit Elementbeziehungen. Das hier behandelte Beispiel ist geradezu ein Musterbeispiel für eine Menge. Die Menge der freigeschalteten Niveaus. Wenn die einzelnen Niveaus (Elemente der Menge) dann auch noch sinnvolle Namen bekommen, bildet die Programmiersprache wunderbar anschaulich ab was der Programmierer eigentlich will. Das ist dann fast schon Umgangssprache und genau das macht die Sache dann auch so sexy.
Richtig ist, dass die Zuweisung
Code:
nicht der reinen Lehre entspricht, weil diese Zuweisung implementationsabhängig ist. Sauberer wäre diese Formulierung:
Niveaus := TNiveauSet(Byte(StrToInt('57')));
Delphi-Quellcode:
Die Zuweisung lautet dann
function IntegerToNiveauSet(NiveauInt: Integer): NiveauSet;
var N: TNiveau; z: Integer; begin z := 1; Result := []; for N := Low(TNiveau) to High(TNiveau) do begin if z and NiveauInt<>0 then include(Result, N); z := z * 2; end; end;
Delphi-Quellcode:
Niveaus := IntegerToNiveauSet(StrToInt('57'));
|
AW: Integer in Set laden
Man könnte sich alternativ auch einen NiveauSet typ anlegen, der z.B. ein Byte ist,
und dann per record helper entsprechende Zugriffsfunktionen anlegen, die das sprachlich auch sehr anschaulich macht (und eventuell noch mehr bequeme Funktionen dazunehmen). Wenn es im Wesentlichen um die sprachliche Erkennbarkeit geht. |
AW: Integer in Set laden
Wäre es nicht viel sinnvoller, nochmal über die Grundlagen von Bitfeldern/Bitmasken zu sprechen?
Denn hier hakt es gerade im Verständnis von DieDolly. |
AW: Integer in Set laden
Zitat:
Ansonsten :thumb: |
AW: Integer in Set laden
Ich würde das auch nie mit Mengen programmieren.
Da Dolly aber Mengen verwendet, könnte es sein, dass Dolly Mengen verwenden muss. Da Dolly eine Zahl als Input erhält, nehme ich an, dass auch die Programmierin/der Programmierer des Inputs schlicht mit Bitmasken gearbeitet hat. |
AW: Integer in Set laden
Zitat:
|
AW: Integer in Set laden
AN dieser Stelle möchte ich noch einmal auf die
![]() |
AW: Integer in Set laden
Delphi-Quellcode:
uses
TypInfo; type TNiveau = (nA, nB, nC, nD, nE, nF); TNiveauSet = set of TNiveau; var n: TNiveau; s: TNiveauSet; begin Byte(s) := 57; for n := Low(TNiveau) to High(TNiveau) do if n in s then Write(GetEnumName(TypeInfo(TNiveau), Ord(n)), ' '); end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 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 by Thomas Breitkreuz