基本形式:
int cmp(const void *a ,const void *b);
分析一下这个基本形式:
函数返回值为 int
形参为两个const void *,意味着这两个参数是const void *类型,也就是一个指针,const代表这个指针所指向的内存单元的值不能被改变。void *,为一个无类型指针,既可以通过强制类型转换,使其转换为任意类型的指针,甚至直接取指向的数据值。
使用方法
对于qsort中
int cmp(const void *a ,const void *b)
{
...
}
cmp()会有三种返回值(以qsort为例):
1、返回一个正数:a排列在b之后;
2、返回0:a、b相等;
3、返回一个负数:a排在b之前;
下面我们看一点实例
1、对int数组升序排序
int cmp(const void *a ,const void *b)
{
return *(int *)a-*(int *)b;//指针a指向的值减指针b指向的值
}
解释一下,为什么这是升序,这是一个一维数组,假设a所在的下标为0,那么b所在的下标就为1,也就是说a是b前面的数,若a-b>0,返回正数,函数会执行将两个数交换的操作,反之a-b<0,函数不执行交换,这样就达到了升序排序的目的。
2、对double数组升序排序
以上方法对double型则不适用,因为cmp返回值为int型,若两个小数差距极小,例如:a=0.15 ,b=0.14,将会被强制转换为0返回,不发生交换
int cmp(const void * a,const void *b)
{
if( *( double* )a > *( double * )b )
return 1;
else if( *( double* )a < *( double * )b )
return -1;
return 0;
}
3、针对直接开辟数组空间而非malloc二级指针得来的二维数组从小到大排序:
int comp(const void*a, const void*b)
return((int*)a)[0]-((int*)b)[0];//这里[]下标换成你自己的排序依据
对比一下一维数组,可以发现一维数组有一个接引用的操作,但是二维数组却没有,按照我的理解,二维数组的写成(int*)a)[0]的形式,[0]就有类似于解引用的功能。
3.1、而针对malloc得来的二维数组从小到大排序:
int comp(const void *a, const void *b)
{
if ((*(int**)a)[0] == (*(int**)b)[0])
return (*(int**)a)[1] - (*(int**)b)[1];//此处则表示先按第一项排序,第一项相同的情况下按第二项
return (*(int**)a)[0] - (*(int**)b)[0];
}
4、对字符串按字典序排序
#include <string.h>
int cmp(const void *a ,const void *b)
{
return strcmp( (char *)a , (char *)b );
}
例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp(const void *a ,const void *b)
{
return strcmp( (char *)a , (char *)b );
}
int main()
{
char A[4][6]={
"abcde",
"aacde",
"accde",
"bcdef"
};
qsort(A,4,sizeof(A[0]),cmp);
for(int i=0 ; i<4 ; i++)
printf("%s\n",A[i]);
}
/*输出:
aacde
abcde
accde
bcdef
*/
5、对结构体升序排序
typedef struct
{
int A;
double B;
char C[];
}Sructure;
int cmp(const void * a,const void *b)
{
//对int的引用
return (*(Sructure *)a).A-(*(Sructure *)a).B;
//对double的引用
if( (*( Sructure* )a).B > (*( Sructure* )b).B )
return 1;
else if( (*( Sructure* )a).B < (*( Sructure* )b).B )
return -1;
return 0;
//对字符串字典序排序
return strcmp( (*(Sructure *)a).C , (*(Sructure *)b).C )
}