StrToInt似乎没有Ansi重载。这是正确的吗?或许我错过了一些东西。 StrToInt坚持将我的ansistrings转换为字符串。
答案 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;