东莞建设网站流程,工程建设股票龙头,wordpress 不显示时间,dedecms是什么大家好#xff0c;我们今天来学习回调函数qsort的实现。 首先让我们打开cplusplus.com找到qsort函数。 我们看到这个函数就可以看到它的头文件和参数信息。
#includestdlib.h
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const voi…大家好我们今天来学习回调函数qsort的实现。 首先让我们打开cplusplus.com找到qsort函数。 我们看到这个函数就可以看到它的头文件和参数信息。
#includestdlib.h
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));让我们看看它的具体参数信息 void* base:待排序数组第一个元素的地址 size_t num:待排序数组的元素个数 size_t size:待排序数组中一个元素的大小单位是字节 int (compar)(const void,const void*))这里是一个函数指针compar指向的是一个比较的函数是用来比较两个元素的里面要放置的是要比较的两个元素的地址 我们要学习这个函数的话我们首先就得来复习下冒泡排序法这里大家可以参考我之前解析冒泡排序法的博客我这里就不给大家一 一介绍了。https://editor.csdn.net/md/?articleId132266676访问这个网址就可以看到我之前写的关于冒泡排序法的博客了。
我们为什么学会了冒泡排序法依然qsort排序函数呢那是因为这个函数的优点它既可以给数组排序也可以给结构体进行排序但是排序时要注意 排序整型数组, 两个整型可以直接使用比较排序结构体数组两个结构体的数据可能不能直接使用比较也就是不同类型的数据比较出大小方法是有差异的 我们看到代码—:
#include stdio.h
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
int main()
{
int arr[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
int i 0;
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
for (i 0; i sizeof(arr) / sizeof(arr[0]); i)
{
printf( %d , arr[i]);
}
printf(\n);
return 0;
}我们在这里定义了数组arr里面我们要给它排序成升序我们只要用引用qsort函数就可以了首先我们给qsort函数传参第一个传的就是数组中第一个元素的地址第二个就是数组中的元素多少我们用sizeof就可以计算出来sizeofarr计算的是整个数组的大小而sizeofarr[0]计算的是每个元素的大小两个值相除那就是这个数组元素的个数因为这是一个整形数组所以我们第三个传参传每个元素的大小只要传sizeofint就可以了最后传的就是一个函数指针的地址了而函数指针中第一个指针存放的地址当然就是数组首元素的地址第二个指针存放的就是要和第一个相比较的元素的地址了我们都了解了那就来看看程序运行的结果吧。 我们现在已经学会使用了这个函数那么我们该怎么进行模拟这个函数的使用呢这就是我们今天要学习的重点了我们今天就来分享如何用qsort函数对整型数组和结构体变量进行排序。
首先我们先来模拟实现整形数组升序的实现
void print_arr(int arr[], int sz)
{int i 0;for (i 0; i sz; i){printf(%d , arr[i]);}printf(\n);
}
void bubble_sort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void*e2))
{//冒泡排序的趟数int i 0;for (i 0; i num - 1; i){//一趟冒泡排序int j 0;for (j 0; j num - 1 - i; j){if (arr[j] arr[j 1]){//交换int tmparr[j];arr[j]arr[j1];arr[j1]tmp;}}}
}void test1()
{int arr[] { 0,1,2,3,4,5,6,7,8,9 };//升序//排序为降序int sz sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);}int main()
{
test();
return 0;
} 这里我们要注意的是 int (cmp)(const void e1, const void* e2) e1是一个指针存放了一个要比较的元素的地址 e2是一个指针存放了一个要比较的元素的地址 e1指向的元素e2指向的元素返回0的数字 e1指向的元素e2指向的元素返回0 e1指向的元素e2指向的元素返回0的数字 我们首先定义数组调用函数test就会跳转到函数test中在这个函数中我们用sz表示数组元素的个数求解的方法还是sizeof的老方法我们在将它调用到函数print_arr中对原数组进行打印再调用函数bubble_sort在里面我们用循环嵌套进行冒泡排序进行打印就行了。 那我们怎么来实现结构体的排序呢因为我们int (cmp)(const void e1, const void* e2)这个函数指针中所有的指针都是void* 型这就相当于一个垃圾桶可以储存任意类型变量的地址这对我们实现结构体的排序密不可分。 我们先定义个结构体变量
struct Stu
{char name[20];//20int age;//4
};
void test2()
{struct Stu arr[] { {zhangsan, 20}, {lisi, 30}, {wangwu, 15}};int sz sizeof(arr) / sizeof(arr[0]);//3bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{//整型数据/字符数据/结构体数据...//可以使用qsort函数对数据进行排序//测试bubble_sort排序整型数据//test1();//测试bubble_sort排序结构体的数据test2();return 0;
}
看到代码块我们发现结构体里面定义了两个类型的变量一个是名字char型一个是年龄int型那么我们对它进行排序的方法就有两种一种是按照名字排序一种按照年龄排序。
int cmp_stu_by_age(const void* e1, const void*e2)
{return ((struct Stu*)e1)-age - ((struct Stu*)e2)-age;
}int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)-name, ((struct Stu*)e2)-name);
}要注意的是我们这里指针的类型是void* 类型要强制转换。这是我们两种方法的比较函数那我们如何进行交换呢我们就看到我们的交换函数
void swap(char* buf1, char* buf2, size_t size)
{int i 0;for (i 0; i size; i){char tmp *buf1;*buf1 *buf2;*buf2 tmp;buf1;buf2;}
}swap((char*)base j * size, (char*)base (j 1) * size, size)我们看到这里的交换函数 (char*)base j * size 确定要交换的第一个数据的地址 (char*)base (j 1) * size 确定要交换的第二个数据的地址 size 确定这俩个数据直接隔了多少个字节方便逐字节进行操作 因为我们的base是char*的指针里面存放的是结构体变量里首元素的地址size表示的是每个元素的大小j * size表示的就是跳过多少个元素而两个元素之间的交换就是字节之间的交换所以我们算出每个每个元素的大小指针代表的char * 型的是一个字节所以两个元素进行一次交换是进行一个字节之间的交换所以我们这里只需要用一个循环就可以实现两个元素的交换了。
接下来我们就来看看完整的代码
#include string.hvoid print_arr(int arr[], int sz)
{int i 0;for (i 0; i sz; i){printf(%d , arr[i]);}printf(\n);
}//int (*cmp)(const void* e1, const void* e2)
//e1是一个指针存放了一个要比较的元素的地址
//e2是一个指针存放了一个要比较的元素的地址
//e1指向的元素e2指向的元素返回0的数字
//e1指向的元素e2指向的元素返回0
//e1指向的元素e2指向的元素返回0的数字
//void swap(char* buf1, char* buf2, size_t size)
{int i 0;for (i 0; i size; i){char tmp *buf1;*buf1 *buf2;*buf2 tmp;buf1;buf2;}
}//泛型编程
void bubble_sort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void*e2))
{//冒泡排序的趟数int i 0;for (i 0; i num - 1; i){//一趟冒泡排序int j 0;for (j 0; j num - 1 - i; j){//if (arr[j] arr[j 1])if(cmp((char*)base j * size, (char*)base (j 1) * size)0){//交换swap((char*)base j * size, (char*)base (j 1) * size, size);}}}
}int cmp_int(const void*e1, const void*e2)
{return *(int*)e1 - *(int*)e2;
}void test1()
{int arr[] { 0,1,2,3,4,5,6,7,8,9 };//升序//排序为降序int sz sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);
} struct Stu
{char name[20];//20int age;//4
};int cmp_stu_by_age(const void* e1, const void*e2)
{return ((struct Stu*)e1)-age - ((struct Stu*)e2)-age;
}int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)-name, ((struct Stu*)e2)-name);
}void test2()
{struct Stu arr[] { {zhangsan, 20}, {lisi, 30}, {wangwu, 15}};int sz sizeof(arr) / sizeof(arr[0]);//3bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}int main()
{//整型数据/字符数据/结构体数据...//可以使用qsort函数对数据进行排序//测试bubble_sort排序整型数据test1();//测试bubble_sort排序结构体的数据test2();return 0;这里我们就只需调用函数test2就可以访问了在test2中我们将所需的参数上传到函数bubble_sort中这里面我们对两个元素进行比较调用到函数int cmp_stu_by_age和int cmp_stu_by_name中在循环里进行比较传参到函数int cmp_stu_by_age(const void* e1, const voide2)和int cmp_stu_by_name(const void e1, const void* e2)中如果返回的值大于0就传参到交换函数中进行交换如果小于0就无需交换顺着循环和下一个元素进行比较。
我们知道年龄是整形的比较大小非常的简单那我们的姓名是char型的那这个怎么比较大小并且排序呢因为我们的名字是字符串所以比较名字之间的大小就是比较字符串之间的大小那么怎么比较字符串的大小呢那就是字符串对应位置的Ascll值的大小如果相等的话就跳到下一个字符相比较以此类推直到比较出大小为止。
让我们看到下面的代码来验证字符串大小的比较
#includestdio.h
#includestring.h
int main()
{char arr1[20] abc;char arr2[20] abe;if (strcmp(arr1, arr2) 0)printf(\n);elseprintf(\n);return 0;
}我们看到图片第一个和第二个字符的Ascll值的大小相同而第三个位置ec所以打印的结果就是。 那么大家看到都应该更加深刻的了解了qsort函数的实现吧今天的分享就到这里谢谢大家。