Partager via


qsort_s

Effectue un tri rapide. Version des améliorations de qsort sécurité décrites dans les fonctionnalités de sécurité du CRT.

Syntaxe

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

Paramètres

base
Début du tableau cible.

number
Taille du tableau dans les éléments.

width
Taille d’élément en octets.

compare
Fonction de comparaison. Le premier argument est le pointeur context . Le deuxième argument est un pointeur vers le key pour la recherche. Le troisième argument est un pointeur vers l’élément de tableau à comparer à key.

context
Pointeur désignant un contexte, qui peut être n’importe quel objet auquel la routine compare doit accéder.

Notes

La fonction qsort_s implémente un algorithme de tri rapide pour trier un tableau d’éléments number, chacun de width octets. L’argument base est un pointeur désignant la base du tableau à trier. qsort_s remplace ce tableau par les éléments triés. L’argument compare est un pointeur désignant une routine fournie par l’utilisateur qui compare deux éléments de tableau et retourne une valeur spécifiant leur relation. qsort_s appelle la routine compare une ou plusieurs fois pendant le tri, passant des pointeurs vers deux éléments de tableau à chaque appel :

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

La routine doit comparer les éléments et retourner l’une des valeurs suivantes :

Valeur retournée Description
< 0 élément 1 inférieur à l’élément 2
0 élément 1 équivalent à l’élément 2
> 0 élément 1 supérieur à l’élément 2

Le tableau est trié par ordre croissant, comme défini par la fonction de comparaison. Pour trier un tableau par ordre décroissant, changez le sens de « supérieur à » et « inférieur à » dans la fonction de comparaison.

Si des paramètres non valides sont passés à la fonction, le gestionnaire de paramètres non valide est appelé, comme décrit dans la validation des paramètres. Si l’exécution est autorisée à continuer, la fonction retourne et errno est définie sur EINVAL. Pour plus d'informations, voir errno, _doserrno, _sys_errlist et _sys_nerr.

Par défaut, l’état global de cette fonction est limité à l’application. Pour modifier ce comportement, consultez État global dans le CRT.

Conditions de l’erreur

key base compare num largeur errno
NULL tous tous tous tous EINVAL
tous NULL tous != 0 tous EINVAL
tous tous tous tous <= 0 EINVAL
tous tous NULL tous tous EINVAL

La fonction qsort_s affiche le même comportement que qsort, mais elle possède le paramètre context et définit errno. Le context paramètre permet aux fonctions de comparaison d’utiliser un pointeur d’objet pour accéder aux fonctionnalités d’objet ou à d’autres informations non accessibles via un pointeur d’élément. L’ajout du context paramètre rend qsort_s plus sécurisé, car context il peut être utilisé pour éviter les bogues de réentrance introduits à l’aide de variables statiques pour rendre les informations partagées disponibles pour la compare fonction.

Spécifications

Routine En-tête requis
qsort_s <stdlib.h> et <search.h>

Pour plus d’informations sur la compatibilité, consultez Compatibility.

Bibliothèques : toutes les versions des bibliothèques runtime C.

Exemple

L’exemple suivant montre comment utiliser le context paramètre dans la qsort_s fonction. Le paramètre context permet d’effectuer des tris thread-safe avec plus de facilité. Au lieu d’utiliser des variables statiques qui doivent être synchronisées pour garantir la sécurité des threads, passez un paramètre context différent à chaque tri. Dans cet exemple, un objet « locale » (paramètres régionaux) est utilisé comme paramètre 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);
}

Exemple de sortie

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

Voir aussi

Recherche et tri
bsearch_s
_lsearch_s
qsort