qsort_s
执行快速排序。 这是 qsort
版本,具有 CRT 中的安全性功能中所述的安全性增强功能。
语法
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
指针。 第二个参数是一个指向用于搜索的 key
的指针。 第三个参数是指向要与 key
进行比较的数组元素的指针。
context
指向上下文的指针,可以是 compare
例程需要访问的任何对象。
注解
qsort_s
函数实现了一种快速排序算法,对数组中的 number
元素(每个元素大小为 width
字节)进行排序。 参数 base
是指向待排序数组的基项的指针。 qsort_s
使用已排序元素覆盖此数组。 参数 compare
是指向用户提供的例程的指针,它比较两个数组元素,并返回指定它们关系的值。 qsort_s
在排序过程中会一次或多次调用 compare
例程,将指针传递给每个调用中的两个数组元素:
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 | compare | num | width | errno |
---|---|---|---|---|---|
NULL |
any | 任意 | 任意 | 任意 | EINVAL |
任意 | NULL |
任意 | != 0 | 任意 | EINVAL |
任意 | 任意 | 任意 | 任意 | <= 0 | EINVAL |
any | 任意 | NULL |
任意 | 任意 | EINVAL |
qsort_s
具有与 qsort
相同的行为,但其具有 context
参数并设置了 errno
。 通过 context
参数,比较函数可以使用对象指针来访问对象功能或通过元素指针无法访问的其他信息。 添加 context
参数可使 qsort_s
更安全,因为 context
可用于避免使用静态变量使共享信息对 compare
函数可用而引入的重新进入 Bug。
要求
例程 | 必需的标头 |
---|---|
qsort_s |
<stdlib.h> 和 <search.h> |
有关兼容性的详细信息,请参阅 兼容性。
库:C 运行时库的所有版本。
示例
下面的示例演示如何使用 qsort_s
函数中的 context
参数。 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