【问题标题】:Val does not work with UInt64?Val 不适用于 UInt64?
【发布时间】:2012-08-04 12:52:25
【问题描述】:

只是好奇为什么以下代码无法将 uint64 值转换为字符串表示形式?

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.

德尔福 XE2

我在这里错过了什么吗?

【问题讨论】:

标签: delphi delphi-xe2


【解决方案1】:

你是对的:Val() 与 UInt64 / QWord 不兼容。

有两个重载函数:

  • 返回浮点值;
  • 返回 Int64(即有符号值)。

您可以改用此代码:

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;

它适用于 Unicode 和非 Unicode 版本的 Delphi。

出错时返回 0。

【讨论】:

  • 我也是+1,但只有一个问题。由于第一个 Pointer 演员表,这不会在 64 位编译器中失败吗?对我来说看起来像是一个错字,你不想在那里使用PChar 吗?
  • @TLama 为什么会这样?对于 32 位和 64 位编译器,指针转换相同。我个人会使用 S[i] 但这主要只是偏好。
  • @David,是的,我后来才意识到(但忘了删除那条评论......)
  • 出错时返回零并不是非常有用。它确实应该处理超出范围的输入。
  • @DavidHeffernan 我有几个这样的函数变体,一个使用var error: integer 附加参数。根据上下文(例如在我们的 mORMot 框架中),返回 0 确实有意义。这只是为了展示一种实现模式。 @TLama 我认为这段代码适用于 Delphi 2 到 XE2,包括 64 位版本的 XE2,以及 FPC。
【解决方案2】:

根据the documentation,

S 是字符串类型的表达式;它必须是形成有符号实数的字符序列。

我同意文档有点含糊;确实,form 到底是什么意思,有符号实数 到底是什么意思(尤其是如果num 是整数类型)?

不过,我认为要突出显示的部分是签名。在这种情况下,您需要一个整数,因此S 必须是一个形成有符号整数的字符序列。但是你的最大值是High(Int64) = 9223372036854775807

【讨论】:

  • Val 是一个内在函数,当传递一个 8 字节宽的整数时会解析为 System._ValInt64。 _ValInt64 返回一个有符号整数。文档很可悲。
【解决方案3】:
function TryStrToInt64(const S: string; out Value: Int64): Boolean;
var
  E: Integer;
begin
  Val(S, Value, E);
  Result := E = 0;
end;

【讨论】:

    【解决方案4】:

    确实缺乏这方面的文档,但我使用来自System.SysUtils 的StrToUInt64 和UIntToStr,它们在字符串和无符号64 位整数之间进行转换。

    我不确定这些是什么时候添加到 Delphi 中的,但它们肯定是在最近的几个版本中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2014-02-19
      • 2011-04-13
      • 2020-11-17
      • 1970-01-01
      相关资源
      最近更新 更多