• C语言进阶 -- 回调函数以及qsort函数的使用


    一、回调函数

    1.1、什么是回调函数???

    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
    上面的说法有点复杂,我们看一段代码理解上面的意思:
    在这里插入图片描述

    二、qsort函数的介绍

    qsort函数

    2.1、qsort函数的使用

    qsort函数就是对数组进行排序,进行升序,不管是什么类型的数组都可以进行排序,int,char,float,结构体类型,这些都是可以的。

    例如:对整型数组进行排序

    int compar(const void* a, const void* b)
    {
    	return (*(int*)a - *(int*)b);
    }
    
    int main()
    {
    	int arr[10] = { 10,5,8,9,4,6,7,2,11,98 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	qsort(arr, sz, sizeof(arr[0]), compar);
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ",arr[i]);
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    例如:对字符数组进行排序

    int compar(const void* a, const void* b)
    {
    	return (*(char*)a - *(char*)b);
    }
    
    int main()
    {
    	int arr[] = { 'w','d','g','h','p'};
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	qsort(arr, sz, sizeof(arr[0]), compar);
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%c ", arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述
    例如:对结构体数组进行排序

    struct Stu 
    {
    	char name[20];
    	int age;
    };
    int compar(const void* a, const void* b)
    {
    	return strcmp(((struct Stu*)a)->name, ((struct Stu*)b)->name);
    }
    
    int main()
    {
    	struct Stu arr[] = { {"zhangsan", 20},{"lisi", 18}};
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	qsort(arr, sz, sizeof(arr[0]), compar);
    	int i = 0;
    	for(i = 0; i < sz; i++)
    	{
    		printf("%s  %d\n", arr[i].name, arr[i].age);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    所以只要我们将sqort中比较的函数实现成我们想要的样子,那样就可是比较任何数据类型了

    2.2、实现sqort函数(冒泡排序实现)

    我们知道排序的算法有很多:冒泡排序,选择排序,插入排序,快速排序…
    而C语言库函数中的sqort函数是由快速排序实现的,那我们就用冒泡排序实现。
    首先:看一个整型的冒泡排序

    void sort(int arr[], int sz)
    {
    	int i = 0;
    	//sz -- 表示数组有多少个元素,sz-1就是要拍序多少趟
    	for (i = 0; i < sz - 1; i++)
    	{
    		int j = 0;
    		//sz - 1 - i 表示这一趟要比较多少对
    		for (j = 0; j < sz - 1 - i; j++)
    		{
    			if (arr[j] > arr[j + 1])
    			{
    				int tmp = arr[j];
    				arr[j] = arr[j + 1];
    				arr[j + 1] = tmp;
    			}
    		}
    	}
    }
    int main()
    {
    	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	sort(arr,sz);
    
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ",arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    2.2.1、参考库函数里面的qsort函数来实现函数参数

    在这里插入图片描述
    注意:void 这是什么意思??*
    void* 就是无类型指针,任何指针类型都可以通过void来存放
    但是void
    不能运算,不能进行±运算,也不能进行解引用操作
    在这里插入图片描述

    在这里插入图片描述

    实现qsort:

    int compare(const void* elem1, const void* elem2)
    {
    	return (int*)elem1 - (int*)elem2;
    }
    
    void Swpa(const void* s1, const void* s2, int width)
    {
    	int i = 0;
    	for (i = 0; i < width; i++)
    	{
    		char* tmp = (char*)s1;
    		(char*)s1 = (char*)s2;
    		(char*)s2 = tmp;
    	}
    }
    void my_qsort(void* base, size_t sz, size_t width,
    	          int(__cdecl* compare)(const void* elem1, const void* elem2))
    {
    	size_t i = 0;
    	//sz -- 表示数组有多少个元素,sz-1就是要拍序多少趟
    	for (i = 0; i < sz - 1; i++)
    	{
    		size_t j = 0;
    		//sz - 1 - i 表示这一趟要比较多少对
    		for (j = 0; j < sz - 1 - i; j++)
    		{
    			if (compare((char*) base+j*width, (char*)base + (j + 1) * width) > 0)
    			{
    				Swpa( (char*)base + j * width, (char*)base + (j + 1) * width , width);
    			}
    		}
    	}
    }
    
    int main()
    {
    	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	my_qsort(arr,sz,sizeof(arr[0]),compare);
    
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ",arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    1、使用自己实现的qsort对结构体进行排序

    
    struct Stu
    {
    	char name[20];
    	int age;
    };
    //比较整型
    int cmp_int(const void* e1, const void*e2)
    {
    	return *(int*)e1 - *(int*)e2;
    }
    //通过姓名来比较
    int cmp_by_name(const void*e1, const void*e2)
    {
    	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
    }
    
    //通过年龄来比较
    int cmp_by_age(const void* e1, const void* e2)
    {
    	return ((struct Stu*)e1)->age -((struct Stu*)e2)->age;
    }
    
    void Swap(char* buf1, char* buf2, int width)
    {
    	int i = 0;
    	for (i = 0; i < width; i++)
    	{
    		char tmp = *buf1;
    		*buf1 = *buf2;
    		*buf2 = tmp;
    		buf1++;
    		buf2++;
    	}
    }
    
    void my_qsort(void* base, size_t sz, size_t width,
    	int(__cdecl* compare)(const void* elem1, const void* elem2))
    {
    	size_t i = 0;
    	//sz -- 表示数组有多少个元素,sz-1就是要拍序多少趟
    	for (i = 0; i < sz - 1; i++)
    	{
    		size_t j = 0;
    		//sz - 1 - i 表示这一趟要比较多少对
    		for (j = 0; j < sz - 1 - i; j++)
    		{
    			if (compare((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
    			{
    				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
    			}
    		}
    	}
    }
    
    
    int main()
    {
    	struct Stu arr[] = { {"zhangsan", 20},{"lisi", 18} };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	my_qsort(arr, sz, sizeof(arr[0]), cmp_by_name);
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%s  %d\n", arr[i].name, arr[i].age);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
  • 相关阅读:
    算法6 排序算法 QuickSort 快速排序
    linux系统Jenkins工具web配置
    jQuery对于链和捕获的实战研究
    分享一个基于Python和Django的产品销售收入数据分析系统源码
    Axios使用
    【JAVA】MyBatisPlus
    华为云耀云服务器HECS安装Docker
    实战Spring Boot集成quartz任务调度框架
    kafka使用教程、快速上手
    服务器端Openresty的Lua 脚本动态生成 HTML 页面
  • 原文地址:https://blog.csdn.net/ryy1999/article/details/127631342