【初心者向け】wcscoll 関数でワイド文字列の照合をマスターしよう


ロケール とは、言語、文字コード、地域、習慣などを含む一連の設定情報です。ロケールによって、文字列の照合順序が異なります。例えば、ドイツ語ロケールでは、"ß" (エスツェット) は "s" と "z" の間に来ますが、英語ロケールではそうではありません。

wcscoll 関数は、以下のプロトタイプを持ちます。

int wcscoll(const wchar_t *s1, const wchar_t *s2);

この関数は、2つのワイド文字列ポインタ s1s2 を引数として受け取り、以下のいずれかの値を返します。

  • 正の値: s2s1 より前に来る
  • 負の値: s1s2 より前に来る
  • 0: s1s2 は同じ照合順序

以下の例では、ドイツ語ロケールで "Straße" と "Straßen" を比較します。

#include <locale.h>
#include <stdio.h>

int main() {
  setlocale(LC_ALL, "de_DE"); // ドイツ語ロケールを設定

  wchar_t str1[] = L"Straße";
  wchar_t str2[] = L"Straßen";

  int result = wcscoll(str1, str2);

  if (result < 0) {
    printf("%ls は %ls より前に来る\n", str1, str2);
  } else if (result > 0) {
    printf("%ls は %ls より後に来る\n", str1, str2);
  } else {
    printf("%ls と %ls は同じ照合順序\n", str1, str2);
  }

  return 0;
}

このプログラムを実行すると、以下の出力が表示されます。

Straße は Straßen より前に来る

これは、ドイツ語ロケールでは "ß" が "s" と "z" の間に来るため、"Straße" が "Straßen" より前に来ることを意味します。

wcscoll 関数の注意点

  • wcscoll 関数は、文字列の長さを考慮しません。つまり、短い文字列が長い文字列よりも前に来る可能性があります。
  • wcscoll 関数は、ロケールによって結果が異なる 可能性があります。
  • wcscoll 関数は、NULL 文字 (\0) で終端されたワイド文字列 のみを受け取ることができます。

wcscoll 関数の代替手段

wcscoll 関数の代替手段として、以下の関数を使用することができます。

  • wmemcmp: ワイド文字列のバイト単位の比較
  • wcsncmp: ワイド文字列の先頭部分の比較
  • wcscmp: ワイド文字列の比較

これらの関数は、ロケールに依存しない比較を行うことができます。



#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
  // 3つのワイド文字列を定義
  wchar_t str1[] = L"Straße";
  wchar_t str2[] = L"Straßen";
  wchar_t str3[] = L"Bahnhof";

  // ドイツ語ロケールを設定
  setlocale(LC_ALL, "de_DE");

  // 各文字列の照合順序を比較
  int result1 = wcscoll(str1, str2);
  int result2 = wcscoll(str2, str3);
  int result3 = wcscoll(str1, str3);

  // 結果を出力
  if (result1 < 0) {
    printf("%ls は %ls より前に来る\n", str1, str2);
  } else if (result1 > 0) {
    printf("%ls は %ls より後に来る\n", str1, str2);
  } else {
    printf("%ls と %ls は同じ照合順序\n", str1, str2);
  }

  if (result2 < 0) {
    printf("%ls は %ls より前に来る\n", str2, str3);
  } else if (result2 > 0) {
    printf("%ls は %ls より後に来る\n", str2, str3);
  } else {
    printf("%ls と %ls は同じ照合順序\n", str2, str3);
  }

  if (result3 < 0) {
    printf("%ls は %ls より前に来る\n", str1, str3);
  } else if (result3 > 0) {
    printf("%ls は %ls より後に来る\n", str1, str3);
  } else {
    printf("%ls と %ls は同じ照合順序\n", str1, str3);
  }

  return 0;
}
Straße は Straßen より前に来る
Straßen は Bahnhof より前に来る
Straße は Bahnhof より前に来る

この出力は、以下のことを示しています。

  • "Straße" は "Bahnhof" より前に来ます。
  • "Straßen" は "Bahnhof" より前に来ます。
  • ドイツ語ロケールでは、"Straße" が "Straßen" より前に来ます。

説明

このプログラムでは、まず setlocale 関数を使用して、ドイツ語ロケールを設定します。次に、3つのワイド文字列 str1str2str3 を定義します。

その後、wcscoll 関数を使用して、各文字列の照合順序を比較します。wcscoll 関数は、2つのワイド文字列ポインタを引数として受け取り、以下のいずれかの値を返します。

  • 正の値: 2つ目の文字列が1つ目の文字列より前に来る
  • 負の値: 1つ目の文字列が2つ目の文字列より前に来る
  • 0: 2つの文字列は同じ照合順序


代替方法が必要となる状況

  • 特定の機能: wcscoll 関数は、照合順序の比較のみを提供します。文字列の先頭部分の比較や、バイト単位の比較など、より特定の機能が必要な場合は、別の関数を使用する必要があります。
  • パフォーマンスの向上: wcscoll 関数は比較的重い処理であるため、パフォーマンスが重要な場合は、より軽量な代替方法を検討する必要があります。
  • ロケール依存性の回避: wcscoll 関数はロケールに依存するため、異なるロケール環境で異なる結果を返す可能性があります。ロケール依存性を避けたい場合は、ロケールに依存しない代替方法を使用する必要があります。

代替方法

関数説明特徴
wcscmpワイド文字列の比較ロケールに依存しない、wcscoll 関数よりも高速
wcsncmpワイド文字列の先頭部分の比較ロケールに依存しない、wcscoll 関数よりも高速
wmemcmpワイド文字列のバイト単位の比較ロケールに依存しない、最速のオプション
strcollバイト列の照合順序の比較ロケール依存、ワイド文字列よりも軽量
strncollバイト列の先頭部分の照合順序の比較ロケール依存、ワイド文字列よりも軽量

以下の例は、wcscmp 関数を使用してワイド文字列を比較する方法を示しています。

#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
  // 2つのワイド文字列を定義
  wchar_t str1[] = L"Straße";
  wchar_t str2[] = L"Straßen";

  // ドイツ語ロケールを設定
  setlocale(LC_ALL, "de_DE");

  // wcscmp 関数を使用して文字列を比較
  int result = wcscmp(str1, str2);

  // 結果を出力
  if (result < 0) {
    printf("%ls は %ls より前に来る\n", str1, str2);
  } else if (result > 0) {
    printf("%ls は %ls より後に来る\n", str1, str2);
  } else {
    printf("%ls と %ls は同じ照合順序\n", str1, str2);
  }

  return 0;
}

このプログラムは、wcscoll 関数を使用する例とほぼ同じ出力を表示します。ただし、wcscmp 関数はロケールに依存しないため、異なるロケール環境でも同じ結果を返します。