Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Val does not work with UInt64?

just curious why the following code fails to convert uint64 value in string representation ?

var
  num: UInt64;
  s: string;
  err: Integer;

begin
  s := '18446744073709551615';  // High(UInt64)
  Val(s, num, err);
  if err <> 0 then
    raise Exception.Create('Failed to convert UInt64 at ' + IntToStr(err));  // returns 20
end.

Delphi XE2

Am I missing something here ?

like image 561
David Unric Avatar asked Feb 20 '23 15:02

David Unric


2 Answers

You are right: Val() is not compatible with UInt64 / QWord.

There are two overloaded functions:

  • One returning a floating point value;
  • One returning an Int64 (i.e. signed value).

You can use this code instead:

function StrToUInt64(const S: String): UInt64;
var c: cardinal;
    P: PChar;
begin
  P := Pointer(S);
  if P=nil then begin
    result := 0;
    exit;
  end;
  if ord(P^) in [1..32] then repeat inc(P) until not(ord(P^) in [1..32]);
  c := ord(P^)-48;
  if c>9 then
    result := 0 else begin
    result := c;
    inc(P);
    repeat
      c := ord(P^)-48;
      if c>9 then
        break else
        result := result*10+c;
      inc(P);
    until false;
  end;
end;

It will work in both Unicode and not Unicode versions of Delphi.

On error, it returns 0.

like image 168
Arnaud Bouchez Avatar answered Feb 22 '23 06:02

Arnaud Bouchez


According to the documentation,

S is a string-type expression; it must be a sequence of characters that form a signed real number.

I agree the documentation is a bit vague; indeed, what exactly does form mean, and exactly what is meant by a signed real number (especially if num is an integer type)?

Still, I think the part to highlight is signed. In this case, you want an integer, and so S must be a sequence of characters that form a signed integer. But then your maximum is High(Int64) = 9223372036854775807

like image 26
Andreas Rejbrand Avatar answered Feb 22 '23 07:02

Andreas Rejbrand