Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Integer erkennen der nicht initalisiert wurde (https://www.delphipraxis.net/92651-integer-erkennen-der-nicht-initalisiert-wurde.html)

Andreas L. 23. Mai 2007 21:53


Integer erkennen der nicht initalisiert wurde
 
Hi,
ich habe folgenden Record

Delphi-Quellcode:
type
 TTrack = record
   Location: String;   //filename (also relative) or url, see TOptions
   Identifier: String; //file hash, etc...
   Title: String;
   Creator: String;    //artist
   Annotation: String; //comment
   Info: String;       //homepage for more informations
   Image: String;      //e. g. a cover. URL or filename required
   Album: String;
   TrackNum: Integer;  //track number/position in the playlist or on the cd
   Duration: Integer;  //length in miliseconds
   Link: String;       //link to some rdf code... see specs.
 end;
Bei einer meiner Funktionen muss später so ein record übergeben werden. Dabei müssen jedoch nicht alle Felder ausgefüllt werden. Damit ich später nicht irgendwelchen Datenmüll abspeichere überprüfe ich natürlich in meiner Funktion ob das jeweilige Feld einen Wert enthält. Jetzt gibts da aber ein Problem mit den Integern. Werden die nicht gesetzt haben die irgendeinen Wert. Wie kann ich jetzt herausfinden ob der User einen Wert übergeben hat oder ob das nur die Zufallszahl ist?

SirThornberry 23. Mai 2007 21:54

Re: Integer erkennen der nicht initalisiert wurde
 
das kannst du nicht feststellen (würde mich zumindest wundern).

Andreas L. 23. Mai 2007 21:56

Re: Integer erkennen der nicht initalisiert wurde
 
Kann man in records denn nicht auch irgendwie Standard-Werte festlegen. Ala bla: Integer = 0; ??

3_of_8 23. Mai 2007 21:57

Re: Integer erkennen der nicht initalisiert wurde
 
Nein. Du kannst sie nur initialisieren. Du kannst nicht definitiv sagen, ob eine Variable initialisiert wurde oder nicht.

fwsp 23. Mai 2007 21:58

Re: Integer erkennen der nicht initalisiert wurde
 
so wie ich das sehe, erwartest du dafür immer nur positve werte, definier doch eine negative konstante
Delphi-Quellcode:
const
  UnDef = -1
auf die du überprüfst.

Andreas L. 23. Mai 2007 21:59

Re: Integer erkennen der nicht initalisiert wurde
 
Delphi-Quellcode:
Du kannst sie nur initialisieren
und wie geht das in Verbindung mit meinen record?

mkinzler 23. Mai 2007 22:03

Re: Integer erkennen der nicht initalisiert wurde
 
Zitat:

und wie geht das in Verbindung mit meinen record?
Du mußt die Einzelnen Teilwerte mit Standards belegen.

3_of_8 23. Mai 2007 22:03

Re: Integer erkennen der nicht initalisiert wurde
 
Kommt drauf an, mit was du das machen willst. Du kannst einen Boolean auf False setzen, einen Integer auf -1 oder einfach mit ZeroMemory den ganzen Record mit 0en überschreiben.

Andreas L. 23. Mai 2007 22:08

Re: Integer erkennen der nicht initalisiert wurde
 
Was ich da bau ist eine Komponente. D. h. ich kann nicht herausfinden wann der User den record benutzt. oder doch?

alzaimar 23. Mai 2007 22:12

Re: Integer erkennen der nicht initalisiert wurde
 
Wenn Du für deine Werte definitiv wissen willst, ob sie mit einem Wert belegt wurden, oder nicht, dann kannst du Variants nehmen. Allen Unkenrufen zum Trotz sind die gar nicht so langsam, wie viele Puristen einem glaubhaft machen wollen (zumindest in Zeiten der GHz Prozessoeren nicht mehr).

Ein Variant ist ein polymorpher Datentyp, der also beliebige Werte (Strings, Arrays, Integer, Float 'you name it') annehmen kann. Daneben gibt es noch die wohldefinierten Werte 'Null' (also nix) sowie 'Unassigned'.

Allerdings belegen Variants mehr Speicherplatz, als generische Datentypen. Wenn die genaue Größe deines Records also irrelevant ist, kann man Variants verwenden.

Eine weitere Möglichkeit ist die Verwendung einer Klasse, wobei Du für jede Property 'X' noch eine weitere' Is_X_defined' deklarierst.

Sobald erstmals schreibend auf die Eigenschaft 'X' zugegriffen wird, liefert 'Is_X_defined' true, sonst eben false.

Andreas L. 23. Mai 2007 22:14

Re: Integer erkennen der nicht initalisiert wurde
 
Wie verwende ich Variants? Was muss ich beim Umbau meines records zum Variant beachten?

Hawkeye219 23. Mai 2007 22:45

Re: Integer erkennen der nicht initalisiert wurde
 
Hallo,
Zitat:

Zitat von 3_of_8
...oder einfach mit ZeroMemory den ganzen Record mit 0en überschreiben.

Aber bitte nicht bei Records mit dynamischen Daten (z.B. AnsiStrings), das führt unter Umständen zu hässlichen Speicherlecks.

Gruß Hawkeye

Amateurprofi 23. Mai 2007 23:29

Re: Integer erkennen der nicht initalisiert wurde
 
Ich halte mich bei solchen Problemen gern an die Intel-Konventionen, die u.a. bei Integer-Typen einen Indefinite-Wert vorsehen.
Ein Indefinite ist ein Integerwert, bei dem nur das höchste Bit = 1 und alle anderen Bits = 0 sind.
Wer das für unsinnig hält der versuche mal einen solchen Wert mit Abs(x) oder mit x:=-x in einen positiven Wert umzuwandeln.

Jelly 24. Mai 2007 06:01

Re: Integer erkennen der nicht initalisiert wurde
 
Du kannst deinen Anwendern auch eine Funktion zur verfügung stellen, mit sovielen Parametern wie dein Record Felder enthält. Dann müssen dein Anwender alle Felder angeben und die nicht benötigten eben 0 übergeben.

Natürlich wirst du dadurch nicht verhindern können, dass trotzdem einer direkt auf den Record zugreift, und gewisse Felder nicht initialisiert. Um das zu vermeiden, mach aus deinem Record eine Klasse, deklarier die vorhandenen Felder in den Private Teil, stelle read-only public Eigenschaften zur Verfügung zum Auslesen der Werte. So kann keiner schreibend auf die Felde zugreifen. Wenn du dann wieder die besagte Mehtode in der Klasse implementierst, zum Setzen der Felder, so kann nichts mehr schief gehen, da immer alle Werte auf einen Ruck gesetzt werden... Ich kürz hier mal das Beispiel ab:

Delphi-Quellcode:
type
  TTrack = class
  private
    FTitle : string ;
    FTrackNum : integer ;
  public
    property Title : string read FTitle ;
    property TrackNum : integer read FTrackNum ;
   
    procedure SetValues (Title : string ; TrackNum : integer) ;
  end ;

implementation

procedure TTrack.SetValues (Title : string ; TrackNum : integer) ;
begin
     Self.FTitle := Title ;
     Self.FTrackNum := TrackNum ;
end ;
[edit=Admin] Mfg, Daniel[/edit]

alzaimar 24. Mai 2007 06:05

Re: Integer erkennen der nicht initalisiert wurde
 
Zitat:

Zitat von Andreas L.
Wie verwende ich Variants? Was muss ich beim Umbau meines records zum Variant beachten?

1. Die Unit 'Variants' einbinden
2. Alle betreffenden Record-Felder als 'Variant' deklarieren.
3. Alle betreffenden Felder mit 'UnAssigned' initialisieren.
4. Fertig

Schau Dir mal die Delphi-Hilfe bezüglich 'Variants' an.

[edit=Admin] Mfg, Daniel[/edit]

Andreas L. 24. Mai 2007 08:54

Re: Integer erkennen der nicht initalisiert wurde
 
Über Variants gibt meine Delphi-Hilfe nicht viel her. Hab es jetzt so ähnlich wie von Jelly vorgeschlagen gemacht:

Delphi-Quellcode:
type
 TTrack = class(TComponent)
   public
   Location: String;   //filename (also relative) or url, see TOptions
   Identifier: String; //file hash, etc...
   Title: String;
   Creator: String;    //artist
   Annotation: String; //comment
   Info: String;       //homepage for more informations
   Image: String;      //e. g. a cover. URL or filename required
   Album: String;
   TrackNum: Integer;  //track number/position in the playlist or on the cd
   Duration: Integer;  //length in miliseconds
   Link: String;       //link to some rdf code... see specs.
   published
   constructor Create(AOwner: TComponent); override;
 end;

...
...

constructor TTrack.Create(AOwner: TComponent);
begin

 inherited Create(AOwner);
 Duration := 0; //initalisieren
 TrackNum := 0; //"  "   "

end;

...
//Aufruf:
procedure TForm1.Button1Click(Sender: TObject);
var
 tr: TTrack;
begin

 tr := TTrack.Create(Self);
 tr.Location := 'sdfsdfdff';
 tr.Creator := 'sdfgdsfds';
 XSPF1.Tracks.Add(tr);

end;
Denkt ihr das ist eine gute Lösung? Funktionieren tuts ;-)

alzaimar 24. Mai 2007 09:21

Re: Integer erkennen der nicht initalisiert wurde
 
Delphi-Quellcode:
Uses Variants;

Type
  TTrack = record
    Location: Variant;   //filename (also relative) or url, see TOptions
    Identifier: Variant; //file hash, etc...
    Title: Variant;
    Creator: Variant;    //artist
    Annotation: Variant; //comment
    Info: Variant;       //homepage for more informations
    Image: Variant;      //e. g. a cover. URL or filename required
    Album: Variant;
    TrackNum: Variant;  //track number/position in the playlist or on the cd
    Duration: Variant;  //length in miliseconds
    Link: Variant;       //link to some rdf code... see specs.
    Procedure InitializeData;
  end;

Procedure TTrack.InitializeData;
Begin
  Location := UnAssigned;
  Identifier := UnAssigned;
  Title := UnAssigned;
  Creator := UnAssigned;
  Annotation := UnAssigned;
  Info := UnAssigned;
  Image := UnAssigned;
  Album := UnAssigned;
  TrackNum := UnAssigned;
  Duration := UnAssigned;
  Link := UnAssigned;
End;

...
Var
  myTrack : TTrack;

Begin
  myTRack.InitializeData;
...
  If myTrack.Location = UnAssigned Then
    Showmessage('Dem Feld <Location> wurde noch nie etwas zugewiesen');
Zitat:

Zitat von Andreas L.
Über Variants gibt meine Delphi-Hilfe nicht viel her....

Oh ja, das stimmt. Haufenweise Müll...

Reinhard Kern 24. Mai 2007 17:22

Re: Integer erkennen der nicht initalisiert wurde
 
Zitat:

Zitat von Amateurprofi
Ich halte mich bei solchen Problemen gern an die Intel-Konventionen, die u.a. bei Integer-Typen einen Indefinite-Wert vorsehen.
Ein Indefinite ist ein Integerwert, bei dem nur das höchste Bit = 1 und alle anderen Bits = 0 sind.
Wer das für unsinnig hält der versuche mal einen solchen Wert mit Abs(x) oder mit x:=-x in einen positiven Wert umzuwandeln.

Das IST Unsinn. Z.B. 16bit-Integer ist definiert als -32768 ... 32767 (mit Vorzeichen) oder 0 ... 65535 (ohne), bei Integern sind alle möglichen Bitmuster gültig. Nach deiner Definition hätte ein 16bit unsigned int mitten im Zahlenraum ein Loch bei 32768!!!

Steht so in allen Lehrbüchern und in der Delphihilfe, und alle Compiler arbeiten auch so, in jeder Programmiersprache, die je erfunden wurde.

Wahrscheinlich hast du das mit einer Real-Darstellung verwechselt, da gibt es tatsächlich NaNs (Not a Number).

Gruss Reinhard

Udontknow 24. Mai 2007 17:29

Re: Integer erkennen der nicht initalisiert wurde
 
Hallo!

Wollte nur kurz daraufhinweisen, daß in Klassen alle Felder bereits mit 0 bwz '' initialisiert sind. Da fällt das Initialisieren also meist flach... ;-)

Cu,
Udontknow

SirThornberry 25. Mai 2007 16:04

Re: Integer erkennen der nicht initalisiert wurde
 
nur so eine Idee - kann man mit überladen von Operatoren da nichts machen. Eine Zuweisung, Addition etc. kann man ja damit regeln. Gibt es da eventuell auch Initialisation?

3_of_8 25. Mai 2007 16:14

Re: Integer erkennen der nicht initalisiert wurde
 
Zitat:

Zitat von Hawkeye219
Hallo,
Zitat:

Zitat von 3_of_8
...oder einfach mit ZeroMemory den ganzen Record mit 0en überschreiben.

Aber bitte nicht bei Records mit dynamischen Daten (z.B. AnsiStrings), das führt unter Umständen zu hässlichen Speicherlecks.

Aber nicht, wenn er ihn initialisiert. Dann ist nämlich noch gar kein AnsiString angelegt und es enstehen auch keine Speicherlecks. Ich würde übrigens in diesem Fall sowieso eine Klasse bevorzugen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:57 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz