介绍:
qsort是一个库函数,用来对数据进行排序,可以排序任意类型的数据。
void qsort (void*base, size_t num, size_t size, int(*compart)(const void*,constvoid*) )
qsort 具有四个参数:
- base 指向待排序的第一个元素,也就是第一个元素的地址。
- num 待排序的元素个数。
- size 待排序的元素的字节数大小。
- compart 是一个函数指针,指向的函数能够比较两个元素。
其中compart 是进行排序的调用函数。
int(*compart)(const void*,const void*) 里面的两个vodi*指向需要排序的元素,也可以写为int(*compart)(const void*e1, const void*e2)
int(*)(const void*,const void*) 是compart的函数指针变量类型。
进行函数调用的时候,compart的返回类型是int 进行调用的参数是void* 类型的指针
void* :
void* 是一种指针类型 void*是一种通用指针类型,void*类型的指针变量,可以接受任意数据类型的地址。
例如:
int a = 10;
int*p = &a;
char*pc = &a;//会出错,因为类型不同
void*pv = &a;//并不会出现报错
至于qsort中为什么使用void*,是因为不知道会有什么类型进行排序,或者说为了许多类型的都能进行排序,才使用void*
用法:
cmp_t 要能够比较 e1和 e2 指向的两个元素,并且给出返回值。
而返回值也是有规定的,如果e1>e2 返回一个比0大的数,e1和e2一样大返回0,e1<e2 返回一个比0小的数。
e1和e2指向的元素进行比较大小,实际上就是*e1和*e2进行比较大小,但是二者都是void * 类型,无法进行*的解引用操作,所以需要进行强制类型转化。
而*(int*)e1 就是将e1的指针类型void*强制转化为int* 并且进行*解引用
而后面return 进行的则是比较大小,当e1大于e2时,相减是大于0的数,返回也是大于0的数
e1等于e2则相减是等于0,返回也是0
e1小于e2相减则是小于0的数,返回也是小于0的数
本质上 compart也是一种回调函数,且是有具体规定的回调函数——qsort内部调动compart这个函数
而具体规定就是int(*compart)(const void*e1, const void*e2)
除了compart这个函数名可以变外,其他必须一致。
compart 单独调用出来就是因为不同的数据类型有着不同的比较方式和方法,所以需要独立出来进行函数调用。
例如:
结构体的比较:
int compart_age(const void* e1, const void* e2)
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
void test2()
{
struct stu s[] = { {"zgabfsab",20},{"lisi",30},{"wangwu",15} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), compart_age);
}
int main()
{
test2();
return 0;
}
整型数组的比较:
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1- *(int*)e2;
}
void test1()
{
int arr[] = { 3, 1, 5, 7, 2, 4, 8, 6, 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,sz,sizeof(arr[0]), cmp_int);
}
int main()
{
test1();
return 0;
}