qsort_s

クイック ソートを実行します。 CRTqsortセキュリティ機能の説明に従ってセキュリティが強化されたバージョン。

構文

void qsort_s(
   void *base,
   size_t num,
   size_t width,
   int (__cdecl *compare )(void *, const void *, const void *),
   void * context
);

パラメーター

base
対象となる配列の先頭。

number
配列サイズ (要素数)。

width
要素のサイズ (バイト単位)。

compare
比較関数。 最初の引数は、 context ポインターです。 2 番目の引数は、検索用の key へのポインターです。 3 番目の引数は、 keyと比較する配列要素へのポインターです。

context
コンテキストへのポインター。コンテキストは、compare ルーチンがアクセスする必要があるどのオブジェクトでもかまいません。

解説

qsort_s 関数は、それぞれが width バイトの number 要素から成る配列を並べ替えるためのクイック ソート アルゴリズムを実装します。 引数 base は、並べ替える配列のベースへのポインターです。 qsort_s は、並べ替えた要素で、この配列を上書きします。 引数 compare は、2 つの配列要素を比較して両者の関係を指定する値を返すユーザー指定のルーチンへのポインターです。 qsort_s は並べ替え中に compare ルーチンを 1 回以上呼び出し、各呼び出しにおいて 2 つの配列要素へのポインターを渡します。

compare( context, (void *) & elem1, (void *) & elem2 );

ルーチンは、要素を比較し、次の値のいずれかを返す必要があります。

戻り値 説明
< 0 要素 1 が要素 2 より 小さい
0 要素 1 は要素 2 に相当します
> 0 要素 1 が要素 2 より 大きい

配列は、比較関数による定義に従って、昇順で並べ替えられます。 配列を降順で並べ替えるには、比較関数の "より大きい" と "より小さい" の意味を入れ替えます。

無効なパラメーターが関数に渡された場合、「パラメーターの検証」で説明されているように、無効なパラメーター ハンドラーが呼び出されます。 実行を続行できる場合、関数は戻り、 errno 次に EINVAL設定されます。 詳細については、「errno」、「_doserrno」、「_sys_errlist」、および「_sys_nerr」を参照してください。

既定では、この関数のグローバル状態の適用対象は、アプリケーションになります。 この動作を変更するには、「CRT のグローバル状態」を参照してください

エラー条件

key base 比較 num errno
NULL any any any any EINVAL
any NULL any != 0 any EINVAL
any any any any <= 0 EINVAL
any any NULL any any EINVAL

qsort_s の動作は、context パラメーターを持ち errno を設定すること以外は qsort と同じです。 この context パラメーターを使用すると、比較関数はオブジェクト ポインターを使用して、オブジェクトの機能や、要素ポインターを介してアクセスできないその他の情報にアクセスできます。 パラメーターを追加するとqsort_scontext静的変数をcontext使用して関数で共有情報を使用できるようにするために、再入バグを回避するために使用できるため、セキュリティがcompare強化されます。

必要条件

ルーチンによって返される値 必須ヘッダー
qsort_s <stdlib.h> および <search.h>

互換性の詳細については、「 Compatibility」を参照してください。

ライブラリ:C ランタイム ライブラリのすべてのバージョン。

次の例では、関数でパラメーターを使用する context 方法を qsort_s 示します。 context パラメーターにより、スレッドセーフの並べ替えをより簡単に実行できるようになります。 スレッド セーフを確保するには同期を取らなければならない静的変数を使用するのではなく、並べ替えごとに異なる context パラメーターを渡します。 この例では、context パラメーターとしてロケール オブジェクトが使用されています。

// crt_qsort_s.cpp
// compile with: /EHsc /MT
#include <stdlib.h>
#include <stdio.h>
#include <search.h>
#include <process.h>
#include <locale.h>
#include <locale>
#include <windows.h>
using namespace std;

// The sort order is dependent on the code page.  Use 'chcp' at the
// command line to change the codepage.  When executing this application,
// the command prompt codepage must match the codepage used here:

#define CODEPAGE_850

#ifdef CODEPAGE_850
// Codepage 850 is the OEM codepage used by the command line,
// so \x00e1 is the German Sharp S in that codepage and \x00a4
// is the n tilde.

char *array1[] = { "wei\x00e1", "weis", "annehmen", "weizen", "Zeit",
                   "weit" };
char *array2[] = { "Espa\x00a4ol", "Espa\x00a4" "a", "espantado" };
char *array3[] = { "table", "tableux", "tablet" };

#define GERMAN_LOCALE "German_Germany.850"
#define SPANISH_LOCALE "Spanish_Spain.850"
#define ENGLISH_LOCALE "English_US.850"

#endif

#ifdef CODEPAGE_1252
   // If using codepage 1252 (ISO 8859-1, Latin-1), use \x00df
   // for the German Sharp S and \x001f for the n tilde.
char *array1[] = { "wei\x00df", "weis", "annehmen", "weizen", "Zeit",
                   "weit" };
char *array2[] = { "Espa\x00f1ol", "Espa\x00f1" "a", "espantado" };
char *array3[] = { "table", "tableux", "tablet" };

#define GERMAN_LOCALE "German_Germany.1252"
#define SPANISH_LOCALE "Spanish_Spain.1252"
#define ENGLISH_LOCALE "English_US.1252"

#endif

// The context parameter lets you create a more generic compare.
// Without this parameter, you would have stored the locale in a
// static variable, thus making sort_array vulnerable to thread
// conflicts.

int compare( void *pvlocale, const void *str1, const void *str2)
{
    char s1[256];
    char s2[256];
    strcpy_s(s1, 256, *(char**)str1);
    strcpy_s(s2, 256, *(char**)str2);
    _strlwr_s( s1, sizeof(s1) );
    _strlwr_s( s2, sizeof(s2) );

    locale& loc = *( reinterpret_cast< locale * > ( pvlocale));

    return use_facet< collate<char> >(loc).compare(s1,
       &s1[strlen(s1)], s2, &s2[strlen(s2)]);

}

void sort_array(char *array[], int num, locale &loc)
{
    qsort_s(array, num, sizeof(char*), compare, &loc);
}

void print_array(char *a[], int c)
{
   for (int i = 0; i < c; i++)
      printf("%s ", a[i]);
   printf("\n");

}

void sort_german(void * Dummy)
{
   sort_array(array1, 6, locale(GERMAN_LOCALE));
}

void sort_spanish(void * Dummy)
{
   sort_array(array2, 3, locale(SPANISH_LOCALE));
}

void sort_english(void * Dummy)
{
   sort_array(array3, 3, locale(ENGLISH_LOCALE));
}

int main( )
{
   int i;
   HANDLE threads[3];

   printf("Unsorted input:\n");
   print_array(array1, 6);
   print_array(array2, 3);
   print_array(array3, 3);

   // Create several threads that perform sorts in different
   // languages at the same time.

   threads[0] = reinterpret_cast<HANDLE>(
                 _beginthread( sort_german , 0, NULL));
   threads[1] = reinterpret_cast<HANDLE>(
                 _beginthread( sort_spanish, 0, NULL));
   threads[2] = reinterpret_cast<HANDLE>(
                 _beginthread( sort_english, 0, NULL));

   for (i = 0; i < 3; i++)
   {
      if (threads[i] == reinterpret_cast<HANDLE>(-1))
      {
         printf("Error creating threads.\n");
         exit(1);
      }
   }

   // Wait until all threads have terminated.
   WaitForMultipleObjects(3, threads, true, INFINITE);

   printf("Sorted output: \n");

   print_array(array1, 6);
   print_array(array2, 3);
   print_array(array3, 3);
}

サンプル出力

Unsorted input:
weiß weis annehmen weizen Zeit weit
Español España espantado
table tableux tablet
Sorted output:
annehmen weiß weis weit weizen Zeit
España Español espantado
table tablet tableux

関連項目

検索と並べ替え
bsearch_s
_lsearch_s
qsort