12

strcoll() 私はそれらの両方を理解しようとしましたが、この参照がそれを言うことを除いて、違いは見つかりませんでした

LC_COLLATE カテゴリで定義されている現在のロケールに従って、2 つの null で終了する文字列を比較します。

考え直して、詳細な回答を求めて別の質問をしていることを知っています.CとC ++の両方で、このロケールは正確には何ですか?

4

2 に答える 2

31

strcmp()文字列のバイトを1つずつ取得し、バイトが何であれ、それらを比較します。

strcoll()バイトを取得し、ロケールを使用して変換してから、結果を比較します。変換は、言語に応じて並べ替えられます。フランス語では、強調された文字は強調されていない文字の後に続きます。したがって、éeの後にあります。ただし、éはfの前にあります。strcoll()それを正しくします。strcmp()あまりよくありません。

ただし、多くの場合strcmp()、使用中の言語(ロケール)で順序付けられた結果を表示する必要がないため、十分です。たとえば、文字列でインデックス付けされた多数のデータにすばやくアクセスする必要がある場合は、その文字列でインデックス付けされたマップを使用します。(少なくともstrcoll()と比較して)一般的に非常に遅いものを使用してソートすることはおそらくまったく役に立たないでしょう。strcmp()

文字の詳細については、UnicodeWebサイトも確認してください。

ロケールに関しては、それは言語です。デフォルトでは「C」に設定されています(多かれ少なかれ、ロケールなし)。場所を選択すると、それに応じてロケールが設定されます。LC_LOCALE環境変数を設定することもできます。実際にはそのような変数はたくさんあります。ただし、一般的には、これらの変数を自動的に考慮して適切な処理を行う事前定義された関数を使用します。(つまり、日付/時刻のフォーマット、数値/メジャーのフォーマット、大文字/小文字の計算など)

于 2012-12-30T00:14:30.523 に答える
3

テストしたすべての Unicode ロケールで何らかの理由で、いくつかの異なるバージョンの glibc で、strcoll() は 2 つのひらがなに対してゼロを返します。これは、 sortuniq、および何らかの方法で文字列の順序と相互作用するすべてのものを壊します。

$ echo -e -n 'い\nろ\nは\nに\nほ\nへ\nと\n' | ソート | ユニーク

い</p>

これは単に修理できないほど壊れています。世界のさまざまな場所の人々は、「い」を「ろ」の前に配置するか後に配置するかについて異なる考えを持っているかもしれませんが、正気な人は誰もそれらを同じと見なしません.

いいえ、ロケールを日本語に設定しても問題ありません。

$ LC_ALL=ja_JP.utf8 LANG=ja_JP.utf8 LC_COLLATE=ja_JP.utf8 echo -e -n 'い\nろ\nは\nに\nほ\nへ\nと\n' | ソート | ユニーク

い</p>

いくつかの公式メーリングリストで議論がありましたが、それは 2002 年のことであり、人々が気にしないため、修正されることはありませんでした: https://www.mail-archive.com/linux-utf8@nl.linux.org /msg02658.html

そのバグはいつか私たちに起こり、最終的に唯一の解決策は、照合ロケールを「C」に設定し、utf-8 エンコーディングの優れたプロパティに依存することでした。すべて日本語のデータを処理する場合、実際には "C" ロケールで作業するべきではないため、これは恐ろしい経験です。

したがって、正気を保つために、strcoll を直接使用しないでください。より安全なバリアントは次のとおりです。

int safe_strcoll(const char *a, const char *b)
{
  int ret = strcoll(a, b);
  if (ret != 0) return ret;
  return strcmp(a, b);
}

strcoll() があなたを台無しにすることを決定した場合に備えて...

編集: 好奇心から実験を繰り返したところ、現在のシステム (glibc 2.29 を使用) は問題なく動作します。ロケールも問題ではありません。

于 2016-07-31T14:05:47.743 に答える