当前位置: 首页 > news >正文

C语言——回调函数的典型示例(分析详解)


🏡润下:个人主页

  🔥个人专栏: 《C语言基础》

🏔️山高万仞,只登一步!

在这里插入图片描述
在这里插入图片描述

文章目录

  • 一.什么是回调函数
  • 二.qsort使用举例
    • 2.1qsort函数的介绍
    • 2.2qsort排序整型
    • 2.3qsort排序结构数据
  • 三.qsort函数的模拟实现

一.什么是回调函数

回调函数是通过函数指针调用的函数

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

实例

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
void test(int(*pf)(int ,int))
{int r = pf(10, 20);printf("%d\n", r);
}
int main()
{test(Add);return 0;
}

在这里插入图片描述
这时Add()就是回调函数,没有直接调用Add( )由该函数的实现方调用(通过函数指针*pf调用Add()函数)。
直接调用的方式:Add(10,20)
在这里插入图片描述
回调函数的应用
以指针章节的转移表为例:🚀C语言——深入解析C语言指针:从基础到实践从入门到精通(四)

#include<stdio.h>
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 Menu()
{printf("**********************\n");printf("****1.Add  2.Sub******\n");printf("****3.Mul  4.Div******\n");printf("*****  0.exit  *******\n");printf("**********************\n");
}
int main()
{int x, y;int input = 1;int ret = 0;do{Menu();printf("请选择:\n");scanf("%d", &input);switch (input){case 1:printf("请输入操作数:");scanf("%d %d", &x, &y);ret = Add(x, y);printf("%d\n", ret);break;case 2:printf("请输入操作数:");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("%d\n", ret);break;case 3:printf("请输入操作数:");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("%d\n", ret);case 4:printf("请输入操作数:");scanf("%d %d", &x, &y);ret = Div(x, y);printf("%d\n", ret);break;case 0:printf("退出\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);return 0;
}

会发现代码有许多冗长的部分,我们可以把冗长的代码用封装成一个函数Calc,通过函数指针作为函数Calc的参数,用来接收不同函数的地址,接受的地址不同,调用的函数就不同,就能实现相对应的功能

#include<stdio.h>
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 Menu()
{printf("**********************\n");printf("****1.Add  2.Sub******\n");printf("****3.Mul  4.Div******\n");printf("*****  0.exit  *******\n");printf("**********************\n");
}void Calc(int (*pf)(int , int ))
{int x = 0;int y = 0;int ret = 0;printf("请输入操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("%d\n", ret);
}
int main()
{int input = 1;do{Menu();printf("请选择:\n");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;
}

图解🤌:
在这里插入图片描述
接受的地址不同,调用的函数就不同,就能实现相对应的功能

二.qsort使用举例

在介绍qsort函数函数之前,之前讲解过冒泡排序,冒泡排序的方式是两个相邻元素逐个比较 ,但是冒泡排序只能进行整型间的排序。冒泡排序还是有一些不便利的地方
qsort是C语言提供的一个排序函数,是基于快速排序算法思想的一种排序方式
优点

1.是现成的排序算法,可以直接使用
2.大部分情况下排序的效率比冒泡排序高
3.qsort函数可以排序任意类型的数据

冒泡排序代码实现: 🚀C语言——深入解析C语言指针:从基础到实践从入门到精通(三)

2.1qsort函数的介绍

通过cplusplus网站查询qsort函数

qsort函数:
void qsort (void* base, size_t num, size_t size,int (compar)(const void,const void*));
参数介绍:
void* base:是指针,指向了被排序元素组的第一个元素
size_t num:base指向被排序数组的元素个数
size_t size:base指向被排序数组的元素大小(长度),单位是字节
int (compar)(const void,const void*)):函数指针,指针指向的函数是用来比较排序数组的两个元素。这个函数是根据排序的标准自己编写的一个比较函数

这个比较函数的返回值是int类型的
当p1>p2时,返回>0
当p1=p2时,返回=0
当p1<p2时,返回<0
默认的排序是升序
在这里插入图片描述

官方网站上qsort函数的介绍
在这里插入图片描述
注:使用qsort要包含头文件
在这里插入图片描述

2.2qsort排序整型

以数组为例✍️

#include<stdio.h>
#include<stdlib.h>
void print_arr(int arr[], int sz)
{int i = 0;for ( i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}
int cmp_arr(const void* p1, const void* p2)
{if (*(int*)p1 > *(int*)p2){return 1;}else if (*(int*)p1 < *(int*)p2){return -1;}else{return 0;}
}
int main()
{int arr[10] = { 2,4,1,7,6,8,9,5,3,10 };int sz = sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);qsort(arr, sz, sizeof(arr[0]), cmp_arr);print_arr(arr, sz);return 0;
}

在这里插入图片描述
com_arr可以直接写成:

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

如果想要进行降序排列:

int cmp_arr(const void* p1, const void* p2)
{if (*(int*)p1 < *(int*)p2){return 1;}else if (*(int*)p1 > *(int*)p2){return -1;}else{return 0;}
}
return (*(int*)p2 - *(int*)p1);//等价

在这里插入图片描述

2.3qsort排序结构数据

结构体成员访问的方式

struct stu 
{char name[20];int age;
};
void test(struct stu *s)
{printf("%d\n", s->age);printf("%s\n", s->name);printf("%d\n", (*s).age);printf("%s\n", (*s).name);
}
int main()
{struct stu s = { "zhangsan",20 };test(&s);return 0;
}

在这里插入图片描述
用qsort函数排序结构体变量

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{char name[30];int age;
};void print_arr(struct stu s[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%s:%d ", s[i].name,s[i].age);}printf("\n");
}
int cmp_age(const void* p1, const void* p2)
{return (*(struct stu*)p1).age -(*(struct stu*)p2).age;
}
void test1()
{struct stu s[] = {{"zhangsan",19},{"wangli",20},{"xiaoming",18}};int sz = sizeof(s) / sizeof(s[0]);print_arr(s, sz);qsort(s, sz, sizeof(s[0]), cmp_age);print_arr(s, sz);
}
int cmp_name(const void* p1, const void* p2)
{return strcmp(((struct stu*)p1)->name , ((struct stu*)p2)->name);
}
void test2()
{struct stu s[] = { {"zhangsan",19},{"wangli",20},{"xiaoming",18} };int sz = sizeof(s) / sizeof(s[0]);print_arr(s, sz);qsort(s, sz, sizeof(s[0]), cmp_name);print_arr(s, sz);
}
int main()
{printf("按年龄打印\n");test1();printf("按名字打印\n");test2();return 0;
}

在这里插入图片描述

三.qsort函数的模拟实现

使用回到函数,模拟实现qsort函数(使用冒泡排序的方式)

#include<stdio.h>
int cmp_int(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
void Swap(char*buff1,char*buff2,size_t width)
{int i = 0;for ( i = 0; i < width; i++){int tmp = *buff1;*buff1 = *buff2;*buff2 = tmp;buff1++;buff2++;}
}
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 sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{int i = 0;for ( i = 0; i < sz-1; i++){int j = 0;for ( j = 0; j < sz-i-1; j++){if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}
void test()
{int arr[] = { 2,4,1,7,6,8,9,5,3,10 };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;
}

在这里插入图片描述
任意类型的数据

struct stu{char name[20];int age;};
void Swap(char*buff1,char*buff2,size_t width)
{int i = 0;for ( i = 0; i < width; i++){int tmp = *buff1;*buff1 = *buff2;*buff2 = tmp;buff1++;buff2++;}
}void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{int i = 0;for ( i = 0; i < sz-1; i++){int j = 0;for ( j = 0; j < sz-i-1; j++){if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}
int cmp_age(const void* p1, const void* p2)
{return (*(struct stu*)p1).age -(*(struct stu*)p2).age;
}
int cmp_name(const void* p1, const void* p2)
{return strcmp(((struct stu*)p1)->name , ((struct stu*)p2)->name);
}
void print_arr2(struct stu s[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%s:%d ", s[i].name, s[i].age);}printf("\n");
}
void test2()
{struct stu s[] = { {"zhangsan",19},{"wangli",20},{"xiaoming",18} };int sz = sizeof(s) / sizeof(s[0]);printf("按名字排序\n");bubble_sort(s, sz, sizeof(s[0]), cmp_name);print_arr2(s, sz);printf("按年龄排序\n");bubble_sort(s, sz, sizeof(s[0]), cmp_age);print_arr2(s, sz);
}int main()
{test2();return 0;
}

在这里插入图片描述

swap函数实现原理
在这里插入图片描述

在这里插入图片描述
紫色框是编写者自己写的比较函数
棕色框是是实现库函数的人(厂商)规定的

http://www.dtcms.com/a/507177.html

相关文章:

  • 雷州网站建设公司网站备案半身照
  • 【AI 风向标】gpt-oss20b 模型测试与评估报告(2025-08-21)
  • Java MyBatis(二)--- 多表查询,# 和 $的区别,SQL注入,数据库连接池,动态SQL
  • 深圳小企业网站建设vs做网站怎么放视频
  • 企业 做网站云虚拟主机搭建网站
  • PHP实现企业微信 会话存档功能
  • centos 7.9 编译安装 freeswitch 1.10.12
  • FT32A103RDAT3是什么芯片?车规级32位国产MCU可替代STM32F103RD
  • uni-app从后端返回的富文本中的视频截取一帧为封面
  • 若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
  • Linux 服务器安全巡检与加固:从命令到实操(CentOS/Ubuntu 通用)
  • 网站如何让百度收录官网seo是什么意思
  • STM32U5G9J-DK2开发板获取RAM占用
  • 从架构到运营:AIOps与O-AA™ 如何实现智能化企业运营
  • 徐州手机网站定制公司哪家好西安大型网站制作
  • 【Day 80】Linux-NAS 和 SAN 存储
  • C++可变参数模板
  • Python下载实战技巧的技术文章大纲
  • PostgreSQL高级特性解析:窗口函数与CTE
  • OpenBMC: BmcWeb处理WebScoket2 产生WebSocket对象
  • 构建AI智能体:六十九、Bootstrap采样在大模型评估中的应用:从置信区间到模型稳定性
  • 图论基础:探索节点与关系的复杂网络
  • 免费建网站 建站之星百度指数免费添加
  • python如何写数据到excel示例
  • Spring Cloud - Spring Cloud 注册中心与服务提供者(Spring Cloud Eureka 概述、微服务快速入门、微服务应用实例)
  • 测试经验分享,登录功能+购物车+限时秒杀(测试点)汇总
  • 腾讯云TVP走进美的,共探智能制造新范式
  • OpenAI 的 Sora 2来了:一场创意革命与失控的狂欢
  • 直播预告 | 时序数据赋能核电数字化转型,TDengine 引领创新新范式
  • 动漫网站建设规划书模板广州网站建设策划