Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi "Cardinal-String" zurück in Cardinal: Exception (https://www.delphipraxis.net/69252-cardinal-string-zurueck-cardinal-exception.html)

ChrisE 12. Mai 2006 13:16


"Cardinal-String" zurück in Cardinal: Exception
 
Hallo,

ich weiß nicht, warum ich diesem Fehler, den ich da wohl mache, noch nie begnet bin, aber jetzt ist es soweit. Folgendes läuft ab:
Ich habe in meinem Programm eine Variable vom Typ Cardinal. Diese wandle ich - um sie in einem Textfile zu speichern - in einen String um.
Wenn ich dann diesen String wieder auslesen und meiner Variablen zuweisen will, kommt immer ein Fehler wenn die Variable Größer als
Delphi-Quellcode:
high(Integer)
ist, was ja bei Cardinal möglich ist.

Ich habe einen einfachen Code geschrieben um den Fehler reproduzieren zu können:

Delphi-Quellcode:
function CardinalStringException: String
var
  c1,c2: Cardinal;
  s: String;
begin
  c1 := 1;
  c1 := c1 + high(Integer);
  s := IntToStr(c1);
  c2 := StrToInt(s); // --> hier tritt der Exception auf :-(
  result := IntToStr(c2);
end;
Was mache ich falsch? Es gibt doch keine StrToCardinal oder so :-(

Vielen Dank für Eure Hilfe.

[Edit] Titel angepasst [/Edit]

Klaus01 12. Mai 2006 13:18

Re: "Cardinal-String" zurück in Cardinal
 
Delphi-Quellcode:
Unit: IdGlobal

function StrToCard(AVal: String): Cardinal;

Parameters

AVal: String

the string containing a numerical value.


Returns

Cardinal - The value the string was converted to.


Description

This function converts a string value into a cardinal (a 32-bit unsigned value) after stripping off spaces and other control characters.
oder
Delphi-Quellcode:
Converts a string that represents an integer (decimal or hex notation) to a number.

Unit

SysUtils

Category

type conversion routines

function StrToInt64(const S: string): Int64;

Description

StrToInt64 converts the string S, which represents an integer-type number in either decimal or hexadecimal notation, into a number. If S does not represent a valid number, StrToInt64 raises an EConvertError exception.
Grüße
Klaus

ChrisE 12. Mai 2006 13:28

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Hallo Klaus,

danke erstmal für die schnelle Antwort. Aber diese Methode gehört doch in den Bereich Indy. Auszug aus der Hilfe:
Common routines and classes used in the Indy component suite.
Ich suche eigentlich eine "Übliche Methode". Vorallem wenn man ein Ini-File (TIniFile) nutzt und dort die Methoden WriteInteger bzw. ReadInteger benutzt gibts auch Fehler. Also was kann man da mit Standardmethoden o.ä. tun?

Die Int64 -Methode ist gut, aber die ist doch "eigentlich" eben nur für Int64. Naja, egal sie tut Ihren zweck. Aber das mit dem Inifiles tut da leider immer noch nicht. MAn muss halt erst in nene Temporären String wandeln und dann schreiben bzw. anderesrum beim Lesen.

Danke nochmals für die super schnelle Antwort :-)

Wenn jemand nochwas weiß / hat, immer her damit - vorallem wegen dem Inifile.

THX

himitsu 12. Mai 2006 13:40

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Also willst du eine Cardinal-Variable in 'ner INI speichern, welche ja "nur" Integer annimmt ... hab ich dat richtig verstanden? :gruebel:

Dann tu doch einfach so, als wenn der Cardinal ein Integer wäre ^^
Delphi-Quellcode:
Var C: Cardinal;

Ini.ReadInteger('...', '...', Integer(C));
Ini.WriteInteger('...', '...', Integer(C));

Klaus01 12. Mai 2006 13:42

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Dann leite doch das Object TIni ab und gebe ihm noch die Methode die fehlt.


Nur ein Ansatz:
Delphi-Quellcode:
function ReadCardinal(const Section, Ident: String; Default: Cardinal): cardinal;
var
  s:String;
begin
  s:=ReadString(section,ident,0);
  result:=StrToInt64(s); // vielleicht noch auf cardinal casten
end;

@ Himitsu
aber was ist wenn C größer als max Integer ist?

Grüße
Klaus

marabu 12. Mai 2006 13:50

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Das Problem ist, das die API Funktionen für die veralteten IniFiles nicht mitspielen. Ich würde TMemIniFile verwenden und alle anderen Vorteile genießen, die diese Klasse mitbringt:

Delphi-Quellcode:
procedure TDemoForm.ExtraGridClick(Sender: TObject);
var
  c: Cardinal;
begin
  with TMemIniFile.Create(ExtractFilePath(ParamStr(0)) + 'temp.ini') do
  begin
    ShowMessage(IntToHex(MaxInt, 8));
    c := Cardinal(MaxInt) shl 1;
    WriteInteger('test', 'card', c);
    c := ReadInteger('test', 'card', 0);
    ShowMessage(IntToHex(c, 8));
    Free;
  end;
end;
Grüße vom marabu

himitsu 12. Mai 2006 13:50

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Zitat:

Zitat von Klaus01
@ Himitsu
aber was ist wenn C größer als max Integer ist?

Kein Problem, der nimmt das an als Minus ... beides sind 32-Bitwerte ... der tut nur so als seis'n Integer ^^

ChrisE 12. Mai 2006 14:13

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Zitat:

Zitat von himitsu
Also willst du eine Cardinal-Variable in 'ner INI speichern, welche ja "nur" Integer annimmt ... hab ich dat richtig verstanden? :gruebel:

Dann tu doch einfach so, als wenn der Cardinal ein Integer wäre ^^
Delphi-Quellcode:
Var C: Cardinal;

Ini.ReadInteger('...', '...', Integer(C));
Ini.WriteInteger('...', '...', Integer(C));

Ich möchte eine Cardinal-Var (voller Bereich also 0..high(Cardinal)) in eine Ini speichern und sie auch wieder lesen. Aber dein Weg klappt super. THX

Zitat:

Zitat von Klaus01
Dann leite doch das Object TIni ab und gebe ihm noch die Methode die fehlt.


Nur ein Ansatz:
Delphi-Quellcode:
function ReadCardinal(const Section, Ident: String; Default: Cardinal): cardinal;
var
  s:String;
begin
  s:=ReadString(section,ident,0);
  result:=StrToInt64(s); // vielleicht noch auf cardinal casten
end;
...

Grüße
Klaus

Das wäre eine Möglichkeit, da hst du recht.

Zitat:

Zitat von marabu
Das Problem ist, das die API Funktionen für die veralteten IniFiles nicht mitspielen. Ich würde TMemIniFile verwenden und alle anderen Vorteile genießen, die diese Klasse mitbringt:

Delphi-Quellcode:
procedure TDemoForm.ExtraGridClick(Sender: TObject);
var
  c: Cardinal;
begin
  with TMemIniFile.Create(ExtractFilePath(ParamStr(0)) + 'temp.ini') do
  begin
    ShowMessage(IntToHex(MaxInt, 8));
    c := Cardinal(MaxInt) shl 1;
    WriteInteger('test', 'card', c);
    c := ReadInteger('test', 'card', 0);
    ShowMessage(IntToHex(c, 8));
    Free;
  end;
end;
Grüße vom marabu

Auch eine super Möglichkeit.


Vielen Dank an alle. Ihr habt mir - wie immer - sehr gut weiter geholfen :-)

Muetze1 12. Mai 2006 14:24

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Gleiches Problem hatte ich auch und warum ist ja nun schon gut erklärt worden. Andere Lösung dazu, welche ich damals gefunden habe:

Str() und Val() sind typspezifisch und arbeiten richtig. Grundlegendes Problem hast du nämlich, wenn du eine Zahl die als String vorliegt und > High(Integer) (MaxInt) ist aber auch gleichzeitig < High(Cardinal) ist - diese wird mit StrToInt nicht ordentlich konvertiert und IntToStr64() löst u.U. unerklärlicherweise trotzdem eine ERangeCheck Exception aus (obwohl es eigentlich ohne Problem klappen sollte) (bei eingeschalteter Bereichsprüfung). Die Val() Funktion arbeitet hingegen fehlerfrei und wandelt auch die Zahlen in dem o.g. Bereich sauber in vorzeichenlose 32 Bit Ganzzahlen um. Str() ist auch das passende Gegenstück, welches richtige Zahlen aus Cardinaltypen ohne Vorzeichen mit der richtigen Grösse erstellt.

himitsu 12. Mai 2006 14:51

Re: "Cardinal-String" zurück in Cardinal: Exceptio
 
Zitat:

Zitat von ChrisE
Ich möchte eine Cardinal-Var (voller Bereich also 0..high(Cardinal)) in eine Ini speichern und sie auch wieder lesen. Aber dein Weg klappt super. THX

Die Erklärung, warum es "super" klappt ist eigentlich ganz einfach.

Cardinal liegt ja irgendwo im Speicher rum und ist 4 Byte (32 Bit, bei den "aktuellen" 32-Bit-Compilern) groß.
Nun ist es dem Speicher aber vollkommen egal was er ist ... das Was kommt erst zu stande, wenn er intepretiert wird, also wenn irgendwas festlegt was welches Bit zu bedeuten hat und wie diese zusammenarbeiten.

Nun ist allerdings ein Integer auch 4 Byte groß demnach kann man ganz locker diese 4 Byte auch mal als Integer interpretieren, oder auch mal als Single (ist ja auch nur ein 4-Byte-Real-Wert), oder wie wäre es mal als Array[0..3] ob Byte? ... alles was gleich groß ist, kann man direkt umwandeln.
Dieses Integer(C), oder Cardinal(i) macht also nichts anders, als den Inhalt der Veriable umzuwandeln, oder besser gesagt anders zu interpretieren.

Das praktische am Integer und Cardinal ist ja auch noch der Umstand, daß deren Formate eigentlich fast gleich sind ... beim Cardinal wird jedem Bit eine Wertigkeit zugeordnet und diese dann addiert, was beim Integer eigentlich genauso ist, nur daß halt da das höchste Bit nicht als Wert, sondern als das Vorzeichen verwendet wird ... somit macht man alao nur mit Integer(C) das höchste Bit, welches im Cardinal den Bereich über MaxInt darstellt das Vorzeichen, also den Bereich unter MinCardinal.

PS:
öffne einfach mal deinen Windowstaschenrechner, stell den auf Wissenschaftlich um
und gib den Wert für MinInt ein (kannst'e aus der OH kopieren),
dann stell den Taschenrechner auf Hexadezimal um und wieder zurück auf Dezimal ...
und schwupps steht da der Wert für MaxInt + 1,
da dieser Taschenrechner mit 64 Bit rechnet und somit die unteren 4 Bytes sozusagen
als Cardinal gelesen werden, wenn sie aus dem Hexadezimalen kommen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:31 Uhr.
Seite 1 von 2  1 2      

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