1

次のプログラムは、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: http://www.delphibasics.co.uk/RTL.asp?Name=CompareStrによると、CompareStr は廃止されたと見なされます。AnsiCompareStr は、http://www.delphibasics.co.uk/RTL.asp?Name=AnsiCompareStr によると、CompareStr の最新の Locale safe 形式であると見なされます

PS: ロケールは en_US.iso885915 および/または en_US.UTF8 です。

PS: Kylix 3 (CrossKylix を使用した Delphi 7 として)

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;
4

1 に答える 1

3

AnsiCompareStr/Text正しい結果を出しています。それらは、一般的なロケールによって定義された順序を反映しています。たとえば、glibc 標準ライブラリからのAnsiCompareStr単純な呼び出しで実装されます。strcoll

問題はあなたの期待にあります。なぜ結果が期待されるのかはわかりませんが、glibc照合が正しく実装されていると期待するのは非常に合理的です。によって暗示されるstrcoll順序は、それが何であれ、一般的なロケールの照合順序です。あなたは質問でそれを述べていません。

おそらく手がかりは、locale safeというフレーズを使用していることです。まあ、CompareXXXロケールにAnsiCompareXXX依存せず、ロケールに依存します。ロケール不変の順序付けを探している場合AnsiCompareXXXは、間違った選択です。

于 2015-10-28T13:00:15.063 に答える