深入理解指针5

一、回调函数是什么?

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

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

下面用代码进行理解当a等于1的时候才会打印hehe。

#include 
void function() {
	printf("hehe");
}
void test(void(*pf)(),int n) {
	if (n==1)
	{
		pf();
	}
}
int main() {
	int a = 0;
	scanf("%d", &a);
	test(function,a);

	return 0;
}

 首先我们将function函数的地址作为参数传递给test函数,此时我们的function函数就是回调函数,这个function函数并不是直接调用实现,而是当我们输入值为1的时候满足发生条件,通过test函数调用function函数。

我们在深入理解指针4里面用代码解决过简单的加减乘除;如果不用转移表的形式,我们能否用回调函数来解决这个问题呢。下面就是解决办法。

#include 
int add(int x, int y) {
	return x + y;
}
int sub(int x, int y) {
	return x - y;
}
int mul(int x, int y) {
	return x * y;
}
int div(int x, int y) {
	return x / y;
}
void test(int (*pf)(int,int) ){
	int a = 0, b = 0;
	scanf("%d %d", &a, &b);
	int r = pf(a,b);
	printf("%d\n", r);
}
void menu1() {
	printf("******************************\n");
	printf("******1.加法******2.减法******\n");
	printf("******3.乘法******4.除法******\n");
	printf("******************************\n");
}
int main() {
	int input = 0;
	int a=0, b=0,r=0;
	do
	{
		menu1();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			test(add);
			break;
		case 2:
			test(sub);
			break;
		case 3:
			test(mul);
			break;
		case 4:
			test(div);
			break;
		default:
			input = 0;
			break;
		}
	
	} while (input);
	return 0;
}

当我们想实现加法时,我们将add函数作为地址传递给test函数 ,再通过test函数来调用add函数。

 这个方法虽然没有用转移表写出来的代码简单,但是它也解决了switch函数过于冗长的问题。

二、qsort使用的举例

1.什么是qsort函数

头文件:#include

语法结构:

void qsort(void* base, size_t num, size_t size,	
            int (*compar)(const void*, const void*));

/*我们把它拆成一段一段来理解
void qsort(void* base,		//base指向了待排序数组中的第一个元素
	       size_t num,		//num是指待排序数组的元素个数
		   size_t size,		//size是指待排序数组的元素大小,单位是字节
		   int (*compar)(const void*, const void*));		//函数指针用来比较base指向数组中任意两个元素的大小
*/

 compar函数的比较原理深入理解指针5_第1张图片 这里的例子中(*(mytype*)a)里面的(mytype*)就是强制类型转换,之所以需要强制类型转化,是因为数组元素传给函数指针时是空指针类型。当你要比较的元素类型是什么就转换为shen么。 

2.使用qsort函数排序整型数据

 当我们全部理解后,现在我们用qsort来新写一个冒泡排序

#include 
#include 
int cmp_int(const void* e1, const void* e2) {
	return *(int*)e1 - *(int*)e2;		//这里cmp函数的比较方法就是随便拿两个数相减作为它的返回值,看它结果大于还是小于还是等于,以此进行排序
}
void print(int arr[], int sz) {
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main() {
	int arr[] = { 1,3,2,4,6,5,8,7,9,0 };
	qsort(arr, 10, sizeof(arr[0]), cmp_int);
	print(arr, 10);
	return 0;
}

 当我们将e1e2改变顺序时,qsort的排序方式也会发生改变。具体解释见上图画圈部分。

3.使用qsort排序结构数据

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
struct stu {
	char name[20];
	int age;
};
void print(struct stu arr[], int sz) {
	for (int i = 0; i < sz; i++) {
		struct stu currentarr = arr[i];
		printf("Name: %s, Age: %d\n", currentarr.name, currentarr.age);        //这个是结构体打印的方法先用for循环取到每一个数组元素结构体,然后再遍历每个结构体的成员变量
	}
}
int cmp_stu_by_name(const void* p1, const void* p2) {
	return strcmp((*(struct stu*)p1).name, (*(struct stu*)p2).name);
}
int main() {
	struct stu arr[3] = { {"zhangsan",18},{"lisi",19},{"wangemazi",20} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
	print(arr, sz);
	return 0;
}

三、qsort函数的模拟实现

我们现在用自己的代码来模拟qsort 

前面3个用户自定义函数是用来模拟实现qsort函数的,后面的print_int和print_struct是打印作用。

#include
#include
struct stu {
	char name[20];
	int age;
};
int cmp1(const void* p1, const void* p2) {
	return *(int*)p1 - *(int*)p2;        //这个是用来比较int
}
int cmp2(const void* p1, const void* p2) {
	return strcmp(((struct stu*)p1)->name ,((struct stu*)p2)->name);        //这个是用来比较struct
}
void swap(char* p1, char* p2,size_t n) {            //这个是用来按字节交换地址,n指的是每个袁术多少字节
	for (int i = 0; i < n; i++)
	{
		char tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2++;
	}
}
void bubble_sort(void* base, size_t sz, size_t size, int(*cmp)(const void* p1, const void* p2)) {
	for (int i = 0; i < sz - 1; i++)        //控制循环趟数
	{
		for (int j = 0; j < sz - 1 - i; j++)        //每趟两个相邻的元素进行比较
		{
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

void print_int(int arr[], int sz) {        //这个起打印功能
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void print_struct(struct stu arr[], int sz) {        //这个起打印功能
	for (int i = 0; i < sz; i++) {
		struct stu currentarr = arr[i];
		printf("name: %s, age: %d\n", currentarr.name, currentarr.age);
	}
}
void test_int() {
	int arr[] = { 2,3,5,1,6,4,8,7,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]),cmp1);
	print_int(arr, sz);
}
void test_struct() {
	struct stu arr[] = { {"zhangsan",15}, {"lisi",156},{"wangermazi",18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp2);
	print_struct(arr, sz);
}
int main() {
	test_int();
	test_struct();
	return 0;
}

 我们写的这个代码其实和qsort差不多,如果我们还想实现其他比较功能只需要自己设计一个cmp函数来实现相应的功能。

你可能感兴趣的:(数据结构)