アプリケーションでの並べ替えの処理

Microsoft Active Directory、Microsoft Exchange、Microsoft Access などの一部のアプリケーションでは、名前 (UTF-16 文字列) でインデックス付けされたロケール文字列と言語文字列の並べ替え可能なデータベースとそれに関連付けられている並べ替えの重みを保持します。

通常、並べ替えは 、独自のロケールのユーザーにとって直感的です。 ただし、アプリケーション開発者にとっては直感的ではない可能性があります。 このトピックでは、アプリケーションでの並べ替え処理に関する考慮事項について説明します。 並べ替えは、言語または序数 (非言語) のいずれかです。

関数の並べ替え

アプリケーションでは、さまざまな並べ替え関数を使用できます。

通常、並べ替え関数は文字列を文字ごとに評価します。 ただし、多くの言語には、従来のスペイン語の 2 文字ペア "CH" など、複数の文字要素があります。 CompareStringCompareStringEx では 、アプリケーションが提供するロケール識別子または名前を使用して、複数文字の要素を識別します。 これに対し、 lstrcmplstrcmpi ではユーザーのロケールが使用されます。

もう 1 つの例として、有効な大文字、タイトル の大文字、小文字の形式である "GI"、"Gi"、"gi" など、2 文字の要素が多数含まれるベトナム語があります。 これらのフォームは、 として 1 つの並べ替え要素として扱われ、大文字と小文字の区別が無視される場合は、等しいと比較されます。 ただし、"gI" は 1 つの要素として有効ではないので、 CompareStringCompareStringExlstrcmpおよび lstrcmpi では、"gI" は 2 つの別個の要素として扱われます。

CompareStringCompareStringExlstrcmplstrcmpiLCMapStringLCMapStringExFindNLSStringFindNLSStringEx の各関数は、既定で "単語の並べ替え" 手法を使用します。 この種類の並べ替えでは、ハイフンとアポストロフィを除くすべての句読点とその他の英数字以外の文字は、任意の英数字の前に来ます。 ハイフンとアポストロフィは、"coop" や "co-op" などの単語が並べ替えられたリストにまとめられるようにするために、他の非英数字文字とは異なる方法で扱われます。

アプリケーションは、単語の並べ替えの代わりに、SORT_STRINGSORT フラグを指定することで、並べ替え関数から "文字列の並べ替え" 手法を要求できます。 文字列の並べ替えでは、ハイフンとアポストロフィは、他の英数字以外の文字と同様に扱われます。 並べ替えシーケンスでの位置は、英数字の前にあります。

次の表は、単語の並べ替えの結果と文字列の並べ替えの結果を比較したものです。

Word並べ替え 文字列の並べ替え
ビレット bill's
法案 ビレット
bill's 法案
できません を実行できません
カント できません
を実行できません カント
con 生協
小屋 con
生協 小屋

 

文字列を言語的に並べ替える

CompareString 関数と CompareStringEx 関数は、言語の等価性をテストします。 アプリケーションでは、文字列を言語的に並べ替えるための正しいロケールでこれらの関数を使用する必要があります。

注意

Unicode との互換性を保つには、アプリケーションで CompareStringEx または Unicode バージョンの CompareString を使用する必要があります。 CompareStringEx を優先するもう 1 つの理由は、Microsoft が相互運用性の理由から、新しいロケールのロケール識別子ではなくロケール名の使用に移行していることです。 Windows Vista 以降でのみ実行されるアプリケーションでは、 CompareStringEx を使用する必要があります。

 

言語的等価性をテストするもう 1 つの方法は、常に単語の並べ替えを使用する lstrcmp または lstrcmpi を使用することです。 lstrcmpi 関数は、NORM_IGNORECASE フラグを使用して CompareString を呼び出し、lstrcmp はそのフラグなしで呼び出します。 ラッパー関数の使用の概要については、「 文字列」を参照してください。

関数は、すべてのロケールに対して言語的に適切な結果を取得します。 次の例に示すように、異なるロケールに対するユーザーの期待は、並べ替え動作で大きく異なる場合があります。

  • 多くのロケールは、ae 合字 (æ) と文字 ae を同じにします。 ただし、アイスランド語 (アイスランド) では別の文字と見なされ、並べ替え順序で Z の後に配置されます。
  • A リング (Å) は通常、A との分音記号の違いだけで並べ替えられます。ただし、スウェーデン語 (スウェーデン) では、並べ替え順序で Z の後に A リングを配置します。

この関数は、Unicode 標準で定義されているコード ポイントが同等のコード ポイントの文字列と正規に等しいことを厳密に検証しようとします。 たとえば、二重引用符 (ü) を含む小文字の "u" を表すコード ポイントは、小文字の "u" と二かっこ ( ̈) を組み合わせた値に正規的に等しくなります。 ただし、正規の等価性は常に可能であるとは限りません。

Windows キーボードと入力メソッド エディター (IME) を使用して入力されたほぼすべてのデータが Unicode 標準で定義されている形式の C 正規化に準拠するため、NLS Unicode 正規化関数を使用して他のプラットフォームからの受信データを変換すると、特にチベット語スクリプトを使用するロケールや、モダン ハングル用のハングル スクリプトを使用するロケールで、最も一貫性のある結果が得られます。 Windows Vista 以降での Unicode 正規化のサポートの詳細については、「文字列を 表す Unicode 正規化の使用」を参照してください。

文字列比較がユーザーの言語設定に従っている場合 (たとえば、順序付けられた ListView コントロールの項目を並べ替える場合)、アプリケーションは次のいずれかを実行できます。

  • ユーザーのロケールを使用して lstrcmp または lstrcmpi を呼び出します。
  • CompareString または CompareStringEx を呼び出して、比較のロケールを定義したり、追加のフラグを渡したり、null 文字を埋め込んだり、文字列の一部に一致する明示的な長さを渡したりします。

たとえば、取得したデータを定義済みのリストまたは内部値と比較する場合など、ロケールに関係なく比較の結果が一貫している必要がある場合、アプリケーションでは、Locale パラメーターが LOCALE_INVARIANT に設定された CompareString または CompareStringEx を使用する必要があります。 CompareString の場合、mystr が "INLAP" の場合でも、次のいずれかの呼び出しが一致します。 この場合、現在のロケールがベトナム語の場合、 lstrcmpi へのロケール依存の呼び出しは失敗します。

Windows XP の場合 :

int iReturn = CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, mystr, -1, _T("InLap"), -1);

以前のオペレーティング システムでは、次の操作を行います。

DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
int iReturn = CompareString(lcid, NORM_IGNORECASE, mystr, -1, _T("InLap"), -1);

文字列を序数で並べ替える

序数 (言語以外) の並べ替えの場合、アプリケーションでは常に CompareStringOrdinal 関数を使用する必要があります。

注意

この関数は、Windows Vista 以降でのみ使用できます。

 

CompareStringOrdinal では、言語的等価性ではなく、2 つの Unicode 文字列を比較してバイナリの等価性をテストします。 このような言語以外の文字列の例としては、NTFS ファイル名、環境変数、ミューテックス、名前付きパイプ、または mailslots の名前があります。 大文字と小文字の区別のオプションを除き、この関数はすべての非バイナリ等価性を無視します。 他の一部の並べ替え関数とは異なり、言語的な並べ替えスキームで重みが与えられないものも含め、すべてのコード ポイントで等しいかどうかをテストします。

次のステートメントはすべて、バイナリ比較では CompareStringOrdinal に適用されますが、 CompareStringCompareStringExlstrcmp、または lstrcmpi には適用されません。

  • Unicode の正規に等価なシーケンス 。たとえば、ラテン小文字 A WITH RING ABOVE (U+00e5) や LATIN SMALL LETTER A + COMBINING RING ABOVE (U+0061 U+030a) など、同一のシーケンスは同一に見えても等しくありません ("å")。
  • Unicode の正規に似た文字列 (LATIN LETTER SMALL CAPITAL Y (U+028f) や LATIN CAPITAL LETTER Y (U+0059) など)は、非常によく似ています ("ʏ" と "Y") で、言語テーブルの一部の特殊な大文字と小文字の重みによってのみ異なる、完全に異なる文字と見なされます。 アプリケーションで bIgnoreCaseTRUE に設定されている場合でも、これらの文字列は異なると比較されます。
  • ZERO WIDTH JOINER (U+200d) など、言語的な並べ替えの重みがないコード ポイントは、コード ポイントの重みを持つものとして扱われます。
  • 新しいバージョンの Unicode で定義されているが、現在の言語テーブルに重みがないコード ポイントは、コード ポイントの重みを持つものとして扱われます。
  • Unicode によって未定義のコード ポイントは、コード ポイントの重みを持つものとして扱われます。
  • アプリケーションで bIgnoreCaseTRUE に設定すると、関数は、言語並べ替えテーブルの情報ではなく、オペレーティング システムの上位テーブルを使用して大文字と小文字をマップします。 したがって、マッピングはロケールに依存しません。

Unicode の正規の同等のシーケンスと Unicode の正規に類似する文字列の詳細については、「 文字列を表す Unicode 正規化の使用」を参照してください。

コード ポイントの並べ替え

一部の Unicode コード ポイントには重みがありません。たとえば、ZERO WIDTH NON JOINER、U+200c です。 並べ替え関数は、並べ替えの重みがないため、重みなしのコード ポイントを意図的に同等と評価します。 Windows Vista 以降では、アプリケーションでは、NLS 文字列比較関数 (特に CompareStringOrdinal) を呼び出して、これらのコード ポイントを並べ替えることができます。これは、リテラル、バイナリの意味 (パスワード検証など) 内のすべてのコード ポイントの評価用です。 Windows Vista より前のオペレーティング システムでは、アプリケーションで C ランタイム関数 strcmp または wcscmp を使用する必要があります。

並べ替え関数は、アプリケーションで hlink_NONSPACE フラグを指定すると、NON SPACING BREVE、U+0306 などの分音記号を無視します。 同様に、これらの関数は、hlink_SYMBOLS フラグが指定されている場合、EQUALS SIGN、U+003d などのシンボルを無視します。 Windows Vista 以降では、アプリケーションは CompareStringOrdinal を呼び出して、リテラルのバイナリ意味で分音記号とシンボル コード ポイントを評価します。 Windows Vista 以前のオペレーティング システムでは、アプリケーションで strcmp または wcscmp を使用する必要があります。

0xFFFFや0x058bなどの一部のコード ポイントは、現在 Unicode では割り当てられません。 これらのコード ポイントは並べ替え時に重みを受け取らず、並べ替え関数に渡すべきではありません。 アプリケーションでは 、IsNLSDefinedString を使用して、データ ストリーム内の Unicode 以外のコード ポイントを検出する必要があります。

注意

IsNLSDefinedString の結果は、新しいバージョンで文字が Unicode に追加され、その後 Windows の並べ替えテーブルに追加される場合に渡される Unicode バージョンによって異なる場合があります。 詳細については、「 並べ替えバージョン管理を使用する」を参照してください。

 

数字を数値として並べ替える

Windows 7 以降では、アプリケーションは SORT_DIGITSASNUMBERS フラグを使用して CompareStringCompareStringExLCMapString、または LCMapStringEx を呼び出すことができます。 このフラグは、数字を数値として扱う並べ替えをサポートしています。たとえば、"10" より前の "2" の並べ替えなどです。

このフラグの使用は、次のような 16 進数には適していません。

01AF
1BCD
002A
12FA
AB1C
AB02
AB12

この場合、"数値" は順に並べ替えられますが、ユーザーは並べ替えの不十分な 16 進数リストを認識します。

マップ文字列

LCMAP_SORTKEYが指定されていない場合、アプリケーションは LCMapString または LCMapStringEx 関数を使用して文字列をマップします。 ソース文字列が null で終わる場合、マップされた文字列は null で終了します。

大文字と小文字の間で変換する場合、関数は 1 つの文字が 1 つの文字にマップされることを保証しません。 たとえば、LCMAP_LOWERCASEフラグとLCMAP_UPPERCASEフラグは、ドイツ語の Sharp S ("ß") をそれ自体にマップできます。 または、LCMAP_UPPERCASE フラグで "ß" を "SS" にマップし、LCMAP_LOWERCASE フラグで "SS" を "ß" にマップすることもできます。 動作は NLS バージョンによって異なります。

大文字と小文字の間で変換する場合、関数はコンテキストに依存しません。 たとえば、LCMAP_UPPERCASE フラグはギリシャ語の小文字 σ ("σ") とギリシャ小文字の最終 σ ("ς") の両方をギリシャ語の大文字 σ ("Σ") に正しくマップしますが、LCMAP_LOWERCASE フラグは常に "Σ" を "σ" にマップし、"ς" にはマップしません。

Locale パラメーターで トルコ語またはアゼルバイジャン語が指定されている場合でも、既定では、関数は小文字の "i" を大文字の "I" にマップします。 トルコ語またはアゼルバイジャン語のこの動作をオーバーライドするには、アプリケーションで LCMAP_LINGUISTIC_CASING を指定する必要があります。 このフラグが適切なロケールで指定されている場合、"ı" (小文字のドットレス I) は小文字の形式の "I" (大文字のドットレス I) と "i" (小文字の点線 I) は小文字の形式の "İ" (大文字の点線 I) です。

カタカナ文字をひらがな文字にマップするためにLCMAP_HIRAGANA フラグを指定し、LCMAP_FULLWIDTHが指定されていない場合、 LCMapString または LCMapStringEx は全角文字のみをひらがなにマップします。 この場合、半角のカタカナ文字は、ひらがなへのマッピングを行わず、変換先の文字列のように配置されます。 アプリケーションでは、半角カタカナ文字をひらがなにマップするLCMAP_FULLWIDTHを指定する必要があります。 この制限の理由は、すべてのひらがな文字が全角文字であるためです。

アプリケーションがソース文字列から文字を取り除く必要がある場合は、NORM_IGNORESYMBOLSフラグとNORM_IGNORENONSPACEフラグが設定され、その他すべてのフラグがクリアされた状態でマッピング関数を呼び出すことができます。 アプリケーションが null で終わらないソース文字列でこれを行う場合、関数は空の文字列を返し、エラーを返さない可能性があります。

並べ替えキーを作成する

アプリケーションで LCMAP_SORTKEYを指定すると、 LCMapString または LCMapStringEx によって 並べ替えキー (バイト値のバイナリ配列) が生成されます。 並べ替えキーは true 文字列ではなく、その値はソース文字列の並べ替え動作を表しますが、意味のある表示値ではありません。

注意

関数は、並べ替えキーの生成中にアラビア語のカシダを無視します。 アプリケーションが 関数を呼び出して、アラビア語の kashida を含む文字列の並べ替えキーを作成する場合、関数は並べ替えキー値を作成しません。

 

並べ替えキーには奇数バイトを含めることができます。 LCMAP_BYTEREV フラグは、偶数バイトのみを反転します。 並べ替えキーの最後のバイト (奇数位置) は反転しません。 終了0x00バイトが奇数位置のバイトの場合は、並べ替えキーの最後のバイトのままです。 終了0x00バイトが偶数バイトの場合は、その前のバイトと位置を交換します。

並べ替えキーを生成する場合、この関数はハイフンとアポストロフィを他の句読点記号とは異なる方法で処理するため、"coop" や "co-op" などの単語はリストに残ります。 ハイフンとアポストロフィ以外のすべての句読点記号は、英数字の前に並べ替えられます。 アプリケーションは、「 関数の並べ替え」で説明されているように、SORT_STRINGSORT フラグを設定することで、この動作を変更できます。

memcmp で使用すると、並べ替えキーは、ソース文字列が CompareString または CompareStringEx で使用される場合と同じ順序を生成します。 並べ替えキーに null バイトが埋め込まれる可能性があるため、 strcmp の代わりに memcmp 関数を使用する必要があります。

並べ替えバージョン管理を使用する

並べ替えテーブルには、定義されたバージョンと NLS バージョンの 2 つの番号があります。 どちらの数値も DWORD 値であり、メジャー値とマイナー値で構成されます。 値の最初のバイトは予約済みで、次の 2 バイトはメジャー バージョンを表し、最後のバイトはマイナー バージョンを表します。 16 進数の用語では、パターンは 0xRRMMMMmm で、R は予約済み、M は major、m は minor と等しくなります。 たとえば、マイナー バージョンが 4 のメジャー バージョン 3 は、0x304として表されます。

定義されたバージョンは、コード ポイントのレパートアを識別し、すべてのロケールで同じです。 メジャー バージョンは、既存のコード ポイントに対する変更を示すためにインクリメントされます。 マイナー バージョンは、コード ポイントが追加されたが、以前に既存のコード ポイントが変更されていないことを示すためにインクリメントされます。

NLS バージョンは ロケール識別子 または ロケール名に固有であり、影響を受けるロケールのコード ポイントの重みの変更を追跡します。 メジャー バージョンは、既に並べ替え可能だったコード ポイントの重みが変更されるとインクリメントされます。 マイナー バージョンは、新しいコード ポイントに重みが割り当てられるとインクリメントされますが、以前に並べ替え可能な他のすべてのコード ポイントの重みは変更されません。

注意

メジャー バージョンの場合、比較を有効にするためにアプリケーションですべてのデータのインデックスを再作成する必要があるため、1 つ以上のコード ポイントが変更されます。 マイナー バージョンの場合、何も移動されませんが、コード ポイントが追加されます。 この種類のバージョンでは、アプリケーションは、以前は並べ替え不可能な値を持つ文字列のインデックスを再作成するだけで済みます。

 

重要

メジャー バージョンは、Windows 8で変更されました。 以前のバージョンの Windows で作成されたデータのインデックスを再作成する必要があります。

 

定義されたバージョンと NLS バージョンはどちらも、LCMAP_SORTKEY フラグを持つ LCMapString 関数または LCMapStringEx 関数を使用して取得した並べ替え可能なコード ポイントに適用され、 CompareStringCompareStringExFindNLSStringFindNLSStringEx 関数でも使用されます。 文字列内の 1 つ以上のコード ポイントが並べ替えられない場合、 IsNLSDefinedString 関数は、その文字列がパラメーターとして渡されるときに FALSE を 返します。

アプリケーションは 、GetNLSVersion または GetNLSVersionEx を呼び出して、並べ替えテーブルの定義済みバージョンと NLS バージョンの両方を取得できます。

データベースのインデックスを作成する

パフォーマンス上の理由から、アプリケーションはデータベースのインデックス作成時に次の手順に従う必要があります。

データベースのインデックスを適切に作成するには

  1. 関数ごとに、NLS バージョン、そのバージョンの並べ替えキー、およびインデックス付き文字列ごとの並べ替え可能性を示す値を格納します。
  2. マイナー バージョンがインクリメントされると、以前は並べ替え不可能な文字列のインデックスを再作成します。 この更新プログラムの影響を受ける文字列は、 IsNLSDefinedString が以前に FALSE を返した文字列に限定する必要があります。
  3. メジャー バージョンがインクリメントされると、更新された重みが任意の文字列の動作を変更する可能性があるため、すべての文字列のインデックスを再作成します。 メジャー バージョンのリリースは非常にまれです。

データベースインデックス作成の問題は、次の理由で発生する可能性があります。

  • それ以降のオペレーティング システムでは、以前のオペレーティング システムで未定義のコード ポイントを定義できるため、並べ替えを変更できます。
  • コード ポイントは、言語サポートの修正により、異なるオペレーティング システムで異なる並べ替えの重みを持つことができます。

このような状況でデータベースのインデックスを再作成する必要性を最小限に抑えるために、アプリケーションは IsNLSDefinedString を使用して定義された文字列と未定義の文字列を区別し、アプリケーションが未定義のコード ポイントを持つ文字列を拒否できるようにします。 GetNLSVersion または GetNLSVersionEx を使用すると、アプリケーションは NLS の変更が特定のインデックス テーブルに使用されるロケールに影響するかどうかを判断できます。 変更がロケールに影響しない場合、アプリケーションはテーブルのインデックスを再作成する必要はありません。

次の表は、並べ替え関数で使用される特定のフラグの効果を示しています。 いずれの場合も、フラグの選択によって、2 つの異なる文字が並べ替えのために等しいと見なされるかどうかが決まります。

文字 1 文字 2 Default NORM_IGNOREWIDTH NORM_IGNOREKANA NORM_IGNOREWIDTH|NORMIGNOREKANA
"あ"
U+3042 ひらがな文字 A
"ガ"
U+30A2 カタカナ文字 A
不平等 不平等 等しい 等しい
"オ"
U+FF75 半角カタカナ文字 O
"オ"
U+30AA カタカナ文字 O
不平等 等しい 不平等 等しい
"B"
U+FF22 FULLWIDTH ラテン大文字 B
"B"
U+0042 英大文字 B
不平等 等しい 不平等 等しい

 

各国語サポートの使用

並べ替え

ロケール情報の取得と設定

Unicode 正規化を使用して文字列を表す

セキュリティに関する考慮事項: 国際機能

[CompareString]

CompareStringEx

CompareStringOrdinal

FindNLSString

FindNLSStringEx

LCMapString

LCMapStringEx