第十二讲:指针(4)

第十二讲:指针(4)

总结:该篇博客详细对以下两个内容进行讲解:

1.回调函数

2.qsort函数

1.回调函数

1.1什么是回调函数

回调函数就是一个通过函数指针调用的函数

如果我们将函数的地址作为参数传递给另一个函数,当通过这个指针被用来调用其指向的函数时,被调用的函数就是回调函数,回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应

下面我们通过代码来理解什么是回调函数:

1.2深入理解并使用回调函数

我们写一个简易的计算器

1.2.1简单写法

c 复制代码
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

这个方法写的十分冗余,下面我们来进行优化

1.2.2优化

c 复制代码
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}

void calc(int (*pa)(int, int)) //使用函数指针变量来接受函数指针
{
	printf("请输入两个操作数:\n");
	int x, y;
	x = 0;
	y = 0;
	scanf("%d %d", &x, &y);
	int set = pa(x, y);
	printf("%d\n", set);
}

int main()
{
	int input = 1;
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(add);  //将想要使用的函数的地址传入,用于调用
			break;
		case 2:
			calc(sub);
			break;
		case 3:
			calc(mul);
			break;
		case 4:
			calc(div);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

我们通过画图来理解回调函数:

2.qsort函数详解

2.1函数简单介绍

这是一个执行快速排序的函数,包含在<stdlib.h>库中

函数原型:

c 复制代码
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

对各个参数进行介绍如下:

1.base:指向要排序数组的首元素的地址

2.num:数组中的元素的个数

3.width:数组中每个元素的大小,单位是字节

4.int (__cdecl *compare )(const void *elem1, const void *elem2 ):

这是一个由编程者自己写的函数,将函数地址传入,函数的形式被规定,该函数定义了如何比较两个元素

对于自己定义的这个函数,通过其返回值决定所排序元素的顺序,遵循以下原则 :

2.3qsort函数使用举例

2.3.1qsort函数排序整形数据

c 复制代码
//使⽤qsort函数排序整型数据

int Sort1(const void* pa, const void* pb)
{
	return (*(int *)pa - *(int*)pb);
}

int main()
{
	int arr[] = { 2,3,4,5,1,6,7,9,10 };

	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), Sort1); //void qsort(void* base, 
	        //size_t num, 
			//size_t width, 
			//int(__cdecl * compare)(const void* elem1, const void* elem2));
	Print(arr, sz);
	return 0;
}

2.3.2qsort函数排序结构数据

c 复制代码
//使⽤qsort函数排序结构数据

//创建一个结构类型,假设为学生数据
struct Stu
{
	char name[20];
	int age;
};

//按照名字排序
int SortByName(const void* pa, const void* pb)
{
	return (strcmp(((struct Stu*)pa)->name, ((struct Stu*)pb)->name));
}

//按照年龄排序
int SortByAge(const void* pa, const void* pb)
{
	return (((struct Stu*)pa)->age - ((struct Stu*)pb)->age);
}

int main()
{
	//给定学生数据
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };

	int sz = sizeof(arr) / sizeof(arr[0]);
	//按照名字排序
	qsort(arr, sz, sizeof(arr[0]), SortByName); //void qsort(void* base, 
										   //size_t num, 
										   //size_t width, 
										   //int(__cdecl * compare)(const void* elem1, const void* elem2));
	//按照年龄排序
	qsort(arr, sz, sizeof(arr[0]), SortByAge); //void qsort(void* base, 
									       //size_t num, 
										   //size_t width, 
										   //int(__cdecl * compare)(const void* elem1, const void* elem2));

	return 0;
}

3.qsort函数的模拟实现

我们使用冒泡排序来进行qsort函数的模拟实现,首先先介绍一下什么是冒泡排序

3.1冒泡排序

目前的排序方式有很多,快速排序,希尔排序,冒泡排序,我们现在使用冒泡排序进行类比排序

c 复制代码
void BubbleSort(int* pa, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (*(pa + j) > *(pa + j + 1))
			{
				int temp = *(pa + j);
				*(pa + j) = *(pa + 1 + j);
				*(pa + 1 + j) = temp;
			}
		}
	}
}

void Print(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", *(arr + i));
}

int main()
{
	int arr[] = { 2,3,4,5,1,6,7,9,10 };

	//冒泡排序
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz);

	//进行打印
	Print(arr, sz);
	return 0;
}

3.2冒泡排序的改造

c 复制代码
//冒泡函数的改造
void Change(char* pa, char* pb, int sz)
{
	for(int i = 0; i<sz; i++)
	{
		char temp = *pa;
		*pa = *pb;
		*pb = temp;
		pa++;
		pb++;
	}
}

void BubbleSort(void* pa, size_t sz, size_t width, int(* compare)(const void* pa, const void* pb))
{
	for (int i = 0; i < sz - 1; i++)  //尽管是改造,但是这两个for循环是不用改变的
	{                                 //第一个for循环表示循环次数
		for (int j = 0; j < sz - 1 - i; j++) //第二个for循环是将两个数进行比较
		{
			//仍然是判断,如果compare函数返回值大于0,进行交换
			if (compare((char*)pa + j * width, (char*)pa + (j + 1) * width) > 0)
				Change((char*)pa + j * width, (char*)pa + (j + 1) * width, width); //进行交换,但是这个交换一次要交换数组类型个字节
		}
	}
}

int main()
{
	//给定学生数据
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };

	//冒泡排序
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz, sizeof(arr[0]), SortByName);  //void qsort(void* base, 
										              //size_t num, 
										              //size_t width, 
										              //int(__cdecl * compare)(const void* elem1, const void* elem2));
	BubbleSort(arr, sz, sizeof(arr[0]), SortByAge);
	return 0;
}
相关推荐
TDengine (老段)27 分钟前
TDengine C/C++ 连接器进阶指南
大数据·c语言·c++·人工智能·物联网·时序数据库·tdengine
TTGGGFF1 小时前
Supertonic 部署与使用全流程保姆级指南(附已部署镜像)
开发语言·python
黎雁·泠崖1 小时前
栈与队列实战通关:3道经典OJ题深度解析
c语言·数据结构·leetcode
木木木一1 小时前
Rust学习记录--C7 Package, Crate, Module
开发语言·学习·rust
love530love1 小时前
升级到 ComfyUI Desktop v0.7.0 版本后启动日志报 KeyError: ‘tensorrt‘ 错误解决方案
开发语言·windows·python·pycharm·virtualenv·comfyui·comfyui desktop
Evand J2 小时前
【MATLAB例程】【空地协同】UAV辅助的UGV协同定位,无人机辅助地面无人车定位,带滤波,附MATLAB代码下载链接
开发语言·matlab·无人机·无人车·uav·协同定位·ugv
chao1898443 小时前
基于MATLAB实现多变量高斯过程回归(GPR)
开发语言·matlab·回归
ytttr8738 小时前
隐马尔可夫模型(HMM)MATLAB实现范例
开发语言·算法·matlab
天远Date Lab8 小时前
Python实战:对接天远数据手机号码归属地API,实现精准用户分群与本地化运营
大数据·开发语言·python
listhi5208 小时前
基于Gabor纹理特征与K-means聚类的图像分割(Matlab实现)
开发语言·matlab