21

文字列の「自然な比較」を実行する Windows API 関数を見つけました。次のように定義されています。

int StrCmpLogicalW(
    LPCWSTR psz1,
    LPCWSTR psz2
);

Delphi で使用するために、次のように宣言しました。

interface
  function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;

implementation
  function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

Unicode文字列を比較するため、ANSI 文字列を比較したい場合に呼び出す方法がわかりません。文字列を WideString にキャストしてから PWideChar にキャストするだけで十分なようですが、このアプローチが正しいかどうかはわかりません。

function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
  Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;

私は文字エンコーディングについてほとんど知らないので、これが私の質問の理由です。この関数は問題ありませんか、それとも比較された両方の文字列を何らかの方法で最初に変換する必要がありますか?

4

4 に答える 4

11

文字列を WideString にキャストすると、必要なものである場合とそうでない場合があるデフォルトのシステム コードページを使用して変換されることに注意してください。通常、現在のユーザーのロケールを使用する必要があります。

WCharFromCharSystem.pasから:

Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
  WCharDest, DestChars);

SetMultiByteConversionCodePageを呼び出して DefaultSystemCodePage を変更できます。

于 2009-06-22T07:18:29.027 に答える
5

タスクを実行する簡単な方法は、関数を次のように宣言することです。

interface
   function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

WideString変数へのポインタであるため(WideChar同じように、AnsiString変数へのポインタAnsiCharです。)

このようにして、DelphiはAnsiStringを自動的に「アップコンバート」WideStringします。

アップデート

そして、私たちは今の世界にいるUnicodeStringので、あなたはそれを作るでしょう:

interface
   function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

UnicodeString変数はまだ\0\0終了した文字列へのポインタであるためですWideChars。だからあなたが呼ぶなら:

var
    s1, s1: AnsiString;
begin
    s1 := 'Hello';
    s2 := 'world';

    nCompare := StrCmpLogicalW(s1, s2);
end;

AnsiStringを受け取る関数にを渡そうとすると、コンパイラは生成されたコードでUnicodeString自動的に呼び出します。MultiByteToWideChar

CompareStringは、Windows7で数値の並べ替えをサポートしています

Windows 7以降、Microsoftは次の機能を追加SORT_DIGITSASNUMBERSしましたCompareString

Windows 7:並べ替え中に数字を数字として扱います。たとえば、「10」の前に「2」を並べ替えます。

これはどれも、文字列を変換またはキャストする必要がある場合を扱う実際の質問に答えるのに役立ちません。

于 2012-05-03T18:32:44.930 に答える
3

関数の ANSI バリアントが存在する可能性があります (チェックしていません)。ほとんどの Wide API は ANSI バージョンとしても利用できます。サフィックスの W を A に変更するだけで準備完了です。その場合、Windows は透過的に前後の変換を行います。

PS: StrCmpLogicalA の欠如を説明する記事は次のとおりです: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx

于 2009-06-21T19:22:10.997 に答える
2

System.StringToOleStrの便利なラッパーであるUseについては、 Gabr's answerMultiByteToWideCharを参照してください。

function AnsiNaturalCompareText(const S1, S2: string): integer;   
var
  W1: PWideChar;
  W2: PWideChar;
begin
  W1 := StringToOleStr(S1);
  W2 := StringToOleStr(S2);
  Result := StrCmpLogicalW(W1, W2);
  SysFreeString(W1);
  SysFreeString(W2);
end;

しかし、Ian Boyd のソリューションは見た目も良く、はるかに優れています。

于 2012-04-20T18:03:21.993 に答える