有一个版本的StrToInt?

时间:2014-06-16 13:04:14

标签: delphi

StrToInt似乎没有Ansi重载。这是正确的吗?或许我错过了一些东西。 StrToInt坚持将我的ansistrings转换为字符串。

2 个答案:

答案 0 :(得分:7)

你是对的。没有StrToInt的ANSI版本。找到ANSI版标准函数的地方是AnsiStrings单位,那里什么也没有。

编写自己的函数来完成工作,或者接受使用StrToInt所需的转换。

编写自己的功能并不难。它可能看起来像这样:

uses 
  SysConst; // for SInvalidInteger
....
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
function AnsiStrToInt(const s: AnsiString): Integer;

  procedure Error;
  begin
    raise EConvertError.CreateResFmt(@SInvalidInteger, [s]);
  end;

var
  Index, Len, Digit: Integer;
  Negative: Boolean;
begin
  Index := 1;
  Result := 0;
  Negative := False;
  Len := Length(s);
  while (Index <= Len) and (s[Index] = ' ') do
    inc(Index);
  if Index > Len then
    Error;
  case s[Index] of
  '-','+':
    begin
      Negative := s[Index] = '-';
      inc(Index);
      if Index > Len then
        Error;
    end;
  end;
  while Index <= Len do
  begin
    Digit := ord(s[Index]) - ord('0');
    if (Digit < 0) or (Digit > 9) then
      Error;
    Result := Result * 10 + Digit;
    if Result < 0 then
      Error;
    inc(Index);
  end;
  if Negative then
    Result := -Result;
end;

这是StrToInt中的缩减版本。它不处理十六进制,并且在错误方面更严格一些。在使用此代码之前,我想测试这是否真的是您的瓶颈。

非常有趣的是,此代码基于RTL源中的代码,无法返回low(Integer)。解决这个问题并不难,但这会使代码变得更加复杂。

答案 1 :(得分:2)

代码实际上非常简单(不支持十六进制字符串,但你不需要它们):

function AnsiStrToInt(const S: RawByteString): Integer;
var
  P: PByte;
  Negative: Boolean;
  Digit: Integer;

begin
  P:= Pointer(S);
// skip leading spaces
  while (P^ = Ord(' ')) do Inc(P);
  Negative:= False;
  if (P^ = Ord('-')) then begin
    Negative:= True;
    Inc(P);
  end
  else if (P^ = Ord('+')) then Inc(P);

  if P^ = 0 then
    raise Exception.Create('No data');

  Result:= 0;
  repeat
    if Cardinal(Result) > Cardinal(High(Result) div 10) then
      raise Exception.Create('Integer overflow');
    Digit:= P^ - Ord('0');
    if (Digit < 0) or (Digit > 9) then
      raise Exception.Create('Invalid char');
    Result:= Result * 10 + Digit;
    if (Result < 0) then begin
      if not Negative or (Cardinal(Result) <> Cardinal(Low(Result))) then
        raise Exception.Create('Integer overflow');
    end;
    Inc(P);
  until (P^ = 0);
  if Negative then Result:= -Result;
end;