kylix AnsiCompareStr 错误?
kylix AnsiCompareStr bug?
以下程序尝试使用 AnsiCompareStr/Text:
program Project5;
{$APPTYPE CONSOLE}
uses StrUtils, SysUtils;
begin
Writeln('Ord(''-'')=', Ord('-'));
Writeln('Ord(''_'')=', Ord('_'));
Writeln('AnsiCompareStr(''-'', ''_'')=', AnsiCompareStr('-', '_'));
Writeln('AnsiCompareText(''-'', ''_'')=', AnsiCompareText('-', '_'));
Writeln('WideCompareStr(''-'', ''_'')=', WideCompareStr('-', '_'));
Writeln('WideCompareText(''-'', ''_'')=', WideCompareText('-', '_'));
Writeln('CompareStr(''-'', ''_'')=', CompareStr('-', '_'));
Writeln('CompareText(''-'', ''_'')=', CompareText('-', '_'));
Readln;
end.
使用 Kylix 编译时,它在 CentOS 5/6 x64 上输出错误结果:
Ord('-')=45
Ord('_')=95
AnsiCompareStr('-', '_')=3 <--- should be negative
AnsiCompareText('-', '_')=3 <--- should be negative
WideCompareStr('-', '_')=3 <--- should be negative
WideCompareText('-', '_')=3 <--- should be negative
CompareStr('-', '_')=-50
CompareText('-', '_')=-50
我想知道为什么 AnsiCompareStr/Text 会给出错误的结果?
PS:CompareStr 根据 http://www.delphibasics.co.uk/RTL.asp?Name=CompareStr . AnsiCompareStr is considered to be the modern, Locale safe form of CompareStr according to http://www.delphibasics.co.uk/RTL.asp?Name=AnsiCompareStr 被认为已过时。
PS: 语言环境是 en_US.iso885915 and/or en_US.UTF8
PS:Kylix 3(如 Delphi 7 和 CrossKylix)
function AnsiCompareStr(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
// glibc 2.1.2 / 2.1.3 implementations of strcoll() and strxfrm()
// have severe capacity limits. Comparing two 100k strings may
// exhaust the stack and kill the process.
// Fixed in glibc 2.1.91 and later.
Result := strcoll(PChar(S1), PChar(S2));
{$ENDIF}
end;
function AnsiCompareText(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
Result := WideCompareText(S1, S2);
{$ENDIF}
end;
AnsiCompareStr/Text
给出了正确的结果。它们反映了流行语言环境定义的顺序。例如 AnsiCompareStr
是通过从 glibc 标准库简单调用 strcoll
来实现的。
问题出在你的意料之中。我不确定您为什么期望得到您所做的结果,但是期望 glibc
正确实现排序规则是很合理的。 strcoll
隐含的顺序是当前语言环境的整理顺序,无论它是什么。你没有在问题中说明这一点。
也许线索是您使用了短语 locale safe。好吧,CompareXXX
独立于语言环境,AnsiCompareXXX
取决于语言环境。如果您正在寻找语言环境不变的顺序,那么 AnsiCompareXXX
是错误的选择。
以下程序尝试使用 AnsiCompareStr/Text:
program Project5;
{$APPTYPE CONSOLE}
uses StrUtils, SysUtils;
begin
Writeln('Ord(''-'')=', Ord('-'));
Writeln('Ord(''_'')=', Ord('_'));
Writeln('AnsiCompareStr(''-'', ''_'')=', AnsiCompareStr('-', '_'));
Writeln('AnsiCompareText(''-'', ''_'')=', AnsiCompareText('-', '_'));
Writeln('WideCompareStr(''-'', ''_'')=', WideCompareStr('-', '_'));
Writeln('WideCompareText(''-'', ''_'')=', WideCompareText('-', '_'));
Writeln('CompareStr(''-'', ''_'')=', CompareStr('-', '_'));
Writeln('CompareText(''-'', ''_'')=', CompareText('-', '_'));
Readln;
end.
使用 Kylix 编译时,它在 CentOS 5/6 x64 上输出错误结果:
Ord('-')=45
Ord('_')=95
AnsiCompareStr('-', '_')=3 <--- should be negative
AnsiCompareText('-', '_')=3 <--- should be negative
WideCompareStr('-', '_')=3 <--- should be negative
WideCompareText('-', '_')=3 <--- should be negative
CompareStr('-', '_')=-50
CompareText('-', '_')=-50
我想知道为什么 AnsiCompareStr/Text 会给出错误的结果?
PS:CompareStr 根据 http://www.delphibasics.co.uk/RTL.asp?Name=CompareStr . AnsiCompareStr is considered to be the modern, Locale safe form of CompareStr according to http://www.delphibasics.co.uk/RTL.asp?Name=AnsiCompareStr 被认为已过时。
PS: 语言环境是 en_US.iso885915 and/or en_US.UTF8
PS:Kylix 3(如 Delphi 7 和 CrossKylix)
function AnsiCompareStr(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
// glibc 2.1.2 / 2.1.3 implementations of strcoll() and strxfrm()
// have severe capacity limits. Comparing two 100k strings may
// exhaust the stack and kill the process.
// Fixed in glibc 2.1.91 and later.
Result := strcoll(PChar(S1), PChar(S2));
{$ENDIF}
end;
function AnsiCompareText(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
Result := WideCompareText(S1, S2);
{$ENDIF}
end;
AnsiCompareStr/Text
给出了正确的结果。它们反映了流行语言环境定义的顺序。例如 AnsiCompareStr
是通过从 glibc 标准库简单调用 strcoll
来实现的。
问题出在你的意料之中。我不确定您为什么期望得到您所做的结果,但是期望 glibc
正确实现排序规则是很合理的。 strcoll
隐含的顺序是当前语言环境的整理顺序,无论它是什么。你没有在问题中说明这一点。
也许线索是您使用了短语 locale safe。好吧,CompareXXX
独立于语言环境,AnsiCompareXXX
取决于语言环境。如果您正在寻找语言环境不变的顺序,那么 AnsiCompareXXX
是错误的选择。