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 d’erreur
key | base | compare | num | width | errno |
---|---|---|---|---|---|
NULL |
n'importe laquelle | tous | tous | tous | EINVAL |
tous | NULL |
n'importe laquelle | != 0 | n'importe laquelle | EINVAL |
tous | tous | tous | n'importe laquelle | <= 0 | EINVAL |
n'importe laquelle | tous | NULL |
tous | n'importe laquelle | 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