delphi中有一个UIntToStr可以让你显示UINT64值,但是StrToUInt在哪里允许用户输入64位无符号值呢?

发布于 2024-11-08 22:34:11 字数 681 浏览 0 评论 0原文

我想将大的 64 位值从十进制或十六进制字符串转换为 64 位 UINT64 数据类型。有一个 UIntToStr 可以帮助将 UINT64 转换为字符串,但无法将 64 位整数转换为无符号值(作为字符串)。这意味着大于 2**63 的整数值不能使用 RTL 以十进制或十六进制表示。这通常不是什么大问题,但用户可能需要输入一个无符号整数值,该值必须作为 64 位无符号整数值存储到注册表中。

procedure HandleLargeHexValue;

var
 x:UINT64;
begin

  x := $FFFFFFFFFFFFFFFE;

  try
  x := StrToInt('$FFFFFFFFFFFFFFFF'); // range error.
  except
    x := $FFFFFFFFFFFFFFFD;
  end;

  Caption := UintToStr(x);

end;

更新 Val 现在可以在 Delphi XE4 及更高版本中工作。在 XE3 及以下版本中,Val('$FFFFFFFFFFFFFFFF') 有效,但 Val('9223372036854775899') 无效。正如 Roeland 在 Quality Central 108740 中指出的那样:在 Delphi XE4 之前,System.Val 在十进制大 UInt64 值方面存在问题。

I want to convert a large 64 bit value from decimal or hex string to 64 bit UINT64 data type. There is a UIntToStr to help converting the UINT64 to string, but no way to convert a 64 bit integer to a unsigned value, as a string. That means integer values greater than 2**63 can not be represented in decimal or hex, using the RTL. This is normally not a big deal, but it can happen that a user needs to input a value, as an unsigned integer, which must be stored into the registry as a 64 bit unsigned integer value.

procedure HandleLargeHexValue;

var
 x:UINT64;
begin

  x := $FFFFFFFFFFFFFFFE;

  try
  x := StrToInt('$FFFFFFFFFFFFFFFF'); // range error.
  except
    x := $FFFFFFFFFFFFFFFD;
  end;

  Caption := UintToStr(x);

end;

Update Val now works fine in Delphi XE4 and up. In XE3 and below Val('$FFFFFFFFFFFFFFFF') works but not Val('9223372036854775899'). As Roeland points out below in Quality Central 108740: System.Val had problems with big UInt64 values in decimal until Delphi XE4.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最单纯的乌龟 2024-11-15 22:34:11

更新:在 XE4 及更高版本中,RTL 错误已修复。这个 hack 仅在 Delphi XE3 或更早版本中有用

,好吧,如果它不存在,我想我总是可以写它。

(我也为此编写了一个非常好的单元测试,但它太大了,无法发布在这里)

unit UIntUtils;

{ A missing RTL function written by Warren Postma. }

interface
  function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
  function StrToUINT64(Value:String):UInt64;

implementation

uses SysUtils,Character;

{$R-}

function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
var
  Start,Base,Digit:Integer;
  n:Integer;
  Nextvalue:UInt64;
begin
  result := false;
  Base := 10;
  Start := 1;
  StrValue := Trim(UpperCase(StrValue));
  if StrValue='' then
    exit;
  if StrValue[1]='-' then
    exit;
  if StrValue[1]='
 then
  begin
    Base := 16;
    Start := 2;
    if Length(StrValue)>17 then // $+16 hex digits = max hex length.
        exit;
  end;
  uValue := 0;
  for n := Start to Length(StrValue) do
  begin
      if Character.IsDigit(StrValue[n]) then
          Digit := Ord(StrValue[n])-Ord('0')
      else if  (Base=16) and (StrValue[n] >= 'A') and (StrValue[n] <= 'F') then
          Digit := (Ord(StrValue[n])-Ord('A'))+10
      else
          exit;// invalid digit.

      Nextvalue := (uValue*base)+digit;
      if (Nextvalue<uValue) then
          exit;
      uValue := Nextvalue;
  end;
  result := true; // success.
end;

function StrToUINT64(Value:String):UInt64;
begin
  if not TryStrToUINT64(Value,result) then
    raise EConvertError.Create('Invalid uint64 value');

end;

end.

UPDATE: In XE4 and later the RTL bug was fixed. This hack is only useful in Delphi XE3 or older

Well, if it ain't there, I guess I could always write it.

(I wrote a pretty good unit test for this too, but its too big to post here)

unit UIntUtils;

{ A missing RTL function written by Warren Postma. }

interface
  function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
  function StrToUINT64(Value:String):UInt64;

implementation

uses SysUtils,Character;

{$R-}

function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
var
  Start,Base,Digit:Integer;
  n:Integer;
  Nextvalue:UInt64;
begin
  result := false;
  Base := 10;
  Start := 1;
  StrValue := Trim(UpperCase(StrValue));
  if StrValue='' then
    exit;
  if StrValue[1]='-' then
    exit;
  if StrValue[1]='
 then
  begin
    Base := 16;
    Start := 2;
    if Length(StrValue)>17 then // $+16 hex digits = max hex length.
        exit;
  end;
  uValue := 0;
  for n := Start to Length(StrValue) do
  begin
      if Character.IsDigit(StrValue[n]) then
          Digit := Ord(StrValue[n])-Ord('0')
      else if  (Base=16) and (StrValue[n] >= 'A') and (StrValue[n] <= 'F') then
          Digit := (Ord(StrValue[n])-Ord('A'))+10
      else
          exit;// invalid digit.

      Nextvalue := (uValue*base)+digit;
      if (Nextvalue<uValue) then
          exit;
      uValue := Nextvalue;
  end;
  result := true; // success.
end;

function StrToUINT64(Value:String):UInt64;
begin
  if not TryStrToUINT64(Value,result) then
    raise EConvertError.Create('Invalid uint64 value');

end;

end.
梦冥 2024-11-15 22:34:11

我必须不同意 Val 解决这个问题。
Val 仅适用于以十六进制编写的大 UInt64 值。当它们以十进制形式写入时,最后一个字符将从字符串中删除,并且结果值是错误的。

请参阅Quality Central 108740:System.Val 在处理大 UInt64 值时出现问题
编辑:这个问题似乎应该在 XE4 中得到解决。无法测试这个。

I must disagree that Val solves this issue.
Val works only for big UInt64 values when they are written in Hex. When they are written in decimal, the last character is removed from the string and the resulting value is wrong.

See Quality Central 108740: System.Val has problems with big UInt64 values
EDIT: It seems that this issue should be solved in XE4. Can't test this.

冷情妓 2024-11-15 22:34:11

对于 Value a UINT64,下面的代码片段给出了 Delphi 2010 上的预期答案,但只有当输入值是十六进制时,

  stringValue := '$FFFFFFFFFFFFFFFF';
  val( stringValue, value, code );

  ShowMessage( UIntToStr( value ));

我只需将 val 包装在一个方便的函数中,然后就完成了。

现在随意烧我吧。我的测试中是否漏掉了一个数字? :D

With Value a UINT64, the code snippet below gives the expected answer on Delphi 2010 but only if the input values are in hexadecimal

  stringValue := '$FFFFFFFFFFFFFFFF';
  val( stringValue, value, code );

  ShowMessage( UIntToStr( value ));

I'd simply wrap val in a convenience function and you're done.

Now feel free to burn me. Am I missing a digit in my tests? :D

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文