C语言提供了给一维数组排序的库函数qsort(),他的声明如下:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
第一个参数:待排序的数组首地址
第二个参数:数组元素个数
第三个参数:数组单个元素占用字节数
第四个参数:回调函数的函数指针,需要用户自己实现回调函数
看完声明,我们先来看看如何使用这个函数,我们先定义一个数组:
因为qsort函数的第四个参数是回调函数的函数指针,所以这里我们需要写一个回调函数,当然qsort对回调函数也是有要求的:
1、如果函数的返回值<0, 那么p1所指向的元素会被排在p2所指向元素的前面
2、如果函数的返回值==0,那么p1所指向元素与p2所指向元素的顺序不确定
3、如果函数的返回值>0, 那么p1所指向元素会被排在p2所指向元素的后面
根据qsort对函数的要求,我们先写一个从小到大排序的回调函数,如下:
注意这里想要取到p1 里面的值,必须先强转为其他类型,因为void*类型不能解引用,因为这里我们是整型数组,所以使用int*;
我们把回调函数放进去,然后排序:
这里第二个参数是数组元素个数,我们使用sizeof(arr)/sizeof(int)是为了方便,如果别人修改了数组成员的个数,我们这行代码不需要修改;
第三个参数,因为我们数组成员是int,所以用int,另外long类型在Linux和Windows下占用的字节数不一样,所以用sizeof()可以跨平台;
排序完成后,我们输出他:
运行:
任务完成!
其实这个回调函数还可以再省一点,这样写:
这里我就不细说了,我说的可能会影响大家的思路,大家仔细看看qsort对回调函数的三个要求,再看看这个return 是否能对的上那三个要求;
另外,这只是从小到大排序的回调函数,如果大家想提升功力,可以尝试从大到小回调函数的实现;
qsort()的其他细节:
1、形参中的地址用void是为了支持任意数据类型,在回调函数中必须具体化,也就是强转为其他类型才能解引用;
2、为什么需要第三个参数?
因为qsort函数不知道数组的数据类型,在函数的内部,操作数据的时候不是按数据类型来操作的,而是按内存块来操作的,如果要交换数组中两个元素的位置不是用赋值语句,而是用memcpy函数;
3、size_t是C语言标准库定义的,在64位系统中是8字节无符号整型:unsigned long long;
4、排序的需求除了升序和降序,还有很多不可预知的情况,所以必须使用回调函数;