目录

指针详解(day20)_#include

8.回调函数

释义

      回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现。

机制

⑴定义一个回调函数;

⑵提供函数实现的一方在初始化的时候,将回调函数的函数​​指针​​注册给调用者;

⑶当特定的事件或条件发生的时候,调用者使用​​函数指针​​调用回调函数对事件进行处理。

作用

​      因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的​​被调用函数​​。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

回调函数在实际中有许多作用。假设有这样一种情况:我们要编写一个库,它提供了某些​​排序算法​​​的实现(如​​冒泡排序​​​、​​快速排序​​​、​​shell排序​​​、shake排序等等),为了能让库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,能让库可用于多种数据类型(int、float、string),此时,可以使用​​函数指针​​,并进行回调。

回调可用于通知机制。例如,有时要在A程序中设置一个​​计时器​​​,每到一定时间,A程序会得到相应的通知,但通知机制的实现者对A程序一无所知。那么,就需一个具有特定原型的函数指针进行回调,通知A程序事件已经发生。实际上,​​API​​​使用一个回调函数SetTimer来通知A程序。如果没有提供回调函数,它还会把一个消息发往程序的​​消息队列​​。(摘自百度百科)

qsort排序函数

实例

void qsort ( 

void* base, //要排序的目标数组
size_t num, //待排序的元素个数
size_t width, //一个元素的大小,单位是字节
int(*cmp)(const void* e1, const void* e2)

);


其中cmp是函数指针,cmp指向的是:排序时,用来比较两个元素的函数。需要自己编写。函数返回值:无

其传参过程如下:

1)传递数组地址

2)确定数组元素个数

3)确定元素大小

4)通过函数指针调用cmp函数

cmp函数

接收cons void* 空类型指针e1,e2的函数,返回值为整型。

如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面

实例

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <stdlib.h>


int compare(const void* a, const void* b)
{
return (*(int*)a - *(int*)b);
}

int main()
{
int values[] = { 40, 10, 100, 90, 20, 25 };
int n;
qsort(values, 6, sizeof(int), compare);
for (n = 0; n < 6; n++)
printf("%d ", values[n]);
return 0;
}

结果

10 20 25 40 90 100//实现数组内元素排序
int (*compar)(const void *, const void *)

详解此参数

参数为函数指针(名为compare的函数,该函数参数为空类型指针1,空类型指针2,返回值为整数)

compare函数须自行编写

 int compare(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}

传递指针p1,指针p2.

1)传参过程已经由数组名作为指针,找到比较对象。

*(int*)p1//p1为指针,但是为空类型指针,所以必须强制转换为int*,即整型指针,才可以解引用

2)传递元素个数

3)传递单个元素大小

4)调用cmp函数(qsort函数可通过回调cmp函数实现排序)

整型数组排序

实例

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <stdlib.h>


int compare(const void* a, const void* b)
{
return (*(int*)a - *(int*)b);
}

int main()
{
int values[] = { 40, 10, 100, 90, 20, 25 };
int n;
qsort(values, 6, sizeof(int), compare);
for (n = 0; n < 6; n++)
printf("%d ", values[n]);
return 0;
}

结果

10 20 25 40 90 100//实现数组内元素排序

结构体排序

struct Stu
{
int age;
char name[20];
};
//比较结构体中元素的年龄
int cmp_age(const void* e1, const void* e2)
{
//本质是比较整形
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//比较名字
int cmp_name(const void* e1, const void* e2)
{
//本质是字符串比较->使用strcmp函数
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void test2()
{
//创建结构体数组,用大括号初始化
struct Stu s[3] = { {19,"Mango"},{18,"Lemon"},{20,"Hello"} };
int sz = sizeof(s) / sizeof(s[0]);
//以年龄排
qsort(s, sz, sizeof(s[0]), cmp_age);
printf("%s %d ", s[0].name, s[0].age);
printf("%s %d ", s[1].name, s[1].age);
printf("%s %d ", s[2].name, s[2].age);
printf("\n");
//以姓名排
qsort(s, sz, sizeof(s[0]), cmp_name);
printf("%s %d ", s[0].name, s[0].age);
printf("%s %d ", s[1].name, s[1].age);
printf("%s %d ", s[2].name, s[2].age);
printf("\n");
}

浮点型数组排序

int cmp_float(const void* e1, const void* e2)
{
if ((*(float*)e1 - *(float*)e2) > 0.00000)
return 1;
else if ((*(float*)e1 - *(float*)e2) == 0.000000)
return 0;
else
return -1;
}
void test3()
{
float arr[5] = { 5.01f,5.01f,0.02f,0.01f,5.001f };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_float);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%f ", arr[i]);
}
}

:结构体排序与浮点型排序引用自CSDN博主「芒果再努力」