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

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

文章目录

  • 前言
  • 一、回调函数是什么
  • 二、回调函数的使用
    • 1.使用标准库中的qsort函数
    • 2.利用qsort函数对结构体数组进行排序
  • 三、实现qsort函数
  • 总结


在这里插入图片描述
先记录一下访问量突破2000啦,谢谢大家支持!!!
这里是上期指针进阶链接,方便大家查看:添加链接描述

前言

大家好呀,今天分享一下上期指针进阶中剩余的内容——回调函数,这个很重要滴,让我们一起来学会学懂他吧!!!


一、回调函数是什么

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

简单来说就是:在另一个函数中利用函数指针调用的函数叫做回调函数

二、回调函数的使用

1.使用标准库中的qsort函数

qsort函数不仅可以排序整型数组,还可以排序结构体等数据类型

代码如下:

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{return (*( int *)p1 - *(int *) p2);
}//这里必须有使用者根据自己的排序依据自己写的比较函数int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };int i = 0;qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);//qsort的第一个参数是排序数组的首元素地址//第二个参数是排序的长度//第三个参数是每个元素的大小//第四参数是使用者自己写的排序依据函数的地址(这里就是使用回调函数)for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){printf( "%d ", arr[i]);}printf("\n");return 0;
}

整型数组排序的运行结果展示:
在这里插入图片描述

2.利用qsort函数对结构体数组进行排序

先看代码如下:

#include<stdio.h>
#inlcude<string.h>
struct stu {int age;char name[20];double score;
};
//依据年龄大小排序的比较函数
int compar_by_age(const void* e1, const void* e2)
{return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
//这是定义一个结构体类型的数组struct stu S[3] = { {21,"FRH",100},{19,"MSY",90},{18,"LZY",85} };int Ssz = sizeof(S) / sizeof(S[0]);qsort(S, Ssz, sizeof(S[0]), compar_by_age);qsort(S, Ssz, sizeof(S[0]), compar_by_name);return 0;
}

排序前后结果对比:
这是排序前结构体数组的顺序:
在这里插入图片描述
这是按照年龄排序后的顺序:
在这里插入图片描述
这是按照姓名排序后的顺序:
在这里插入图片描述

三、实现qsort函数

我们先来看一下qsort函数在标准库中的模样:
在这里插入图片描述
他没有返回值,四个参数分别是:
1、qsort的第一个参数是排序数组的首元素地址
2、第二个参数是排序的长度
3、第三个参数是每个元素的大小
4、第四参数是使用者自己写的排序依据函数的地址(这里就是使用回调函数)

作者是依据冒泡排序实现的qosrt函数,我们之间上代码:
#include<stdio.h>
#inlcude<string.h>
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
//依据整型大小排序的比较函数
int int_cmp(const void * p1, const void * p2)
{//这里都会将接收到的地址转换为所需要比较的类型return (*( int *)p1 - *(int *) p2);
}//这里排序中交换两个元素的交换函数
void Swap(char* x, char* y,int size)
{
//利用char* 接收需要交换的元素,可以保证对其每个字节进行交换从而实现整体全部字节的交换
//size就是该元素所占字节的大小,决定每次交换循环几次int i = 0;for (i = 0; i < size; i++){char temp = *x;*x = *y;*y = temp;x++;y++;}
}void Bubble_Sort(void* base, size_t num, size_t size,int (*compar)(const void*, const void*))
{int i = 0;for (i = 0; i < num - 1; i++){int j = 0;for (j = 0; j < num - 1 - i; j++){//为什么要将首元素地址转换为char* 类型呢?//因为:这样可以保证任何类型数组在排序比较时能够访问到其中的每一个元素//这个设计是真的巧妙if (compar(((char*)base + j * size), ((char*)base + (j+1)*size))>0){Swap(((char*)base + j * size), ((char*)base + (j+1)*size), size);}}}
}

对其进行测试:

int main()
{int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };struct stu S[3] = { {21,"FRH",100},{19,"MSY",90},{18,"LZY",85} };int Ssz = sizeof(S) / sizeof(S[0]);int sz = sizeof(arr) / sizeof(arr[0]);Bubble_Sort(arr,sz,sizeof(arr[0]),compar_by_int);Print(arr, sz);Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_age);Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_name);return 0;
}

可以得到,排序结果和上面调用标注库中qsort函数的结果是相同的
在这里插入图片描述

总结

关于回调函数的分享就到这里啦,希望qsort函数可以帮助到大家,博主感觉他真的是很有用,以后会尽量使用到他的,希望本篇文章可以帮助到大家,谢谢大家阅读!!!

相关文章:

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

文章目录 前言一、回调函数是什么二、回调函数的使用1.使用标准库中的qsort函数2.利用qsort函数对结构体数组进行排序 三、实现qsort函数总结 先记录一下访问量突破2000啦&#xff0c;谢谢大家支持&#xff01;&#xff01;&#xff01; 这里是上期指针进阶链接&#xff0c;方便…...

PHP手术麻醉系统源码,自动生成麻醉和护理医疗文书

一套手术麻醉系统源码&#xff0c;可二次开发 手术室麻醉临床信息系统&#xff08;AIMS&#xff09;是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期&#xff0c;对病人进行全程跟踪与信息管理&#xff0c;自动集成病人HIS、LIS、RIS、PACS信息&#xff0…...

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】

通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…...

iPhone删除的照片能恢复吗?不小心误删了照片怎么找回?

iPhone最近删除清空了照片还能恢复吗&#xff1f;大家都知道&#xff0c;照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活&#xff0c;也留住了我们的美好瞬间&#xff0c;具有极其重要的纪念价值。 照片不小心误删是一件非常难受的事&#xff0c;那么iP…...

LeetCode--HOT100题(32)

目录 题目描述&#xff1a;138. 复制带随机指针的链表&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;138. 复制带随机指针的链表&#xff08;中等&#xff09; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &…...

SAP MM学习笔记24-以评估收货(评价)和非评估收货(非评价)

SAP 中 有评价入库&#xff08;评估收货&#xff09;和非评价入库&#xff08;非评估收货&#xff09;两种入库方式。 一般来说在库品目会采用评价入库&#xff0c;而消费品目&#xff0c;会采用非评价入库。 其实评价入库&#xff0c;非评价入库对外都无所谓的&#xff0c;人…...

Hadoop的DataNode无法启动的解决方案

Hadoop重启一次&#xff0c;里面的数据需要重新导入&#xff0c;发现无法导入数据&#xff0c;查看jps发现是DataNode没有启动&#xff0c;重新启动发现也无法启动&#xff0c;原因是前面重新启动NameNode&#xff0c;里面的文件格式化一次&#xff0c;DataNode的文件不一致&am…...

re中的match和search有什么区别?

问题:请说明以下re模块中的match和search有什么区别? re.match()与re.search()的区别 re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,结果返回None,而re.search()匹配整个字符串,直到找到一个匹配 re.search() re.search()扫描整个字符串并…...

《内网穿透》无需公网IP,公网SSH远程访问家中的树莓派

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…...

.net连接mysql,提示找不到请求的 .Net Framework Data Provider。可能没有安装

开发完成的.net程序需要连接mysql数据库&#xff0c;在个人电脑上运行没问题&#xff0c;别人运行时提示“提示找不到请求的 .Net Framework Data Provider。可能没有安装”。经过查询&#xff0c;安装Connector/NET 8.1.0&#xff0c;下载地址如下所示&#xff1a; https://d…...

销售自动化管理软件是什么,销售自动化管理软件有什么优势

阅读本文您可以了解&#xff1a;1、销售自动化管理软件是什么&#xff1b;2、销售自动化管理软件的优势 一、销售自动化管理软件是什么 销售自动化管理软件是一种用于帮助企业有效管理销售流程和客户关系的工具。它集成了各种功能和工具&#xff0c;以简化和自动化销售团队的任…...

MySQL 函数

mysql 函数语法 create function 函数名&#xff08;参数名 参数类型&#xff0c;。。。&#xff09; returns type —返回值类型 ----returns 有个 s [characteristics…] begin 函数体 ### 函数体中肯定有 return 语句 end 参数列表 指定参数为 IN | out | INOUT 只对存储过程…...

爬虫逆向实战(六)--猿人学第四题

一、数据接口分析 主页地址&#xff1a;猿人学第四题 1、抓包 通过抓包可以发现数据接口是api/match/4 2、判断是否有加密参数 请求参数是否加密&#xff1f; 无请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 响应数据无加密&#xff0c;但是返回的却是html代码…...

【大数据Hive】hive 事务表使用详解

目录 一、前言 二、Hive事务背景知识 hive事务实现原理 hive事务原理之 —— delta文件夹命名格式 _orc_acid_version 说明 bucket_00000 合并器(Compactor) 二、Hive事务使用限制 参数设置 客户端参数设置 客户端参数设置 三、Hive事务使用操作演示 操作步骤 客…...

网络层协议

网络层协议 IP协议基本概念协议头格式网段划分特殊的IP地址IP地址的数量限制私有IP地址和公网IP地址路由IP协议头格式后续 在复杂的网络环境中确定一个合适的路径 IP协议 承接上文&#xff0c;TCP协议并不会直接将数据传递给对方&#xff0c;而是交付给下一层协议&#xff0c;…...

JWT(JSON Web Token )令牌

1、介绍 jwt就是将原始的json数据格式进行了安全的封装&#xff0c;这样就可以直接基于jwt在通信双方安全的进行信息传输了。 2、jwt组成 第一部分&#xff1a;Header(头&#xff09;&#xff0c; 记录令牌类型、签名算法等。 例如&#xff1a;{"alg":"HS256…...

leetcode 力扣刷题 滑动窗口 部分题解(记录)

力扣刷题 滑动窗口相关的部分题解 209. 长度最小的子数组904. 水果成篮76. 最小覆盖子串 209. 长度最小的子数组 leetcode题目链接 209.长度最小的子数组 题目内容是这样的&#xff1a;给定一个含有 n个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的…...

Intellij IDEA SBT依赖分析插件

可分析模块和传递依赖 安装完插件后&#xff0c;由于IDEA BUG&#xff0c;会出现两个分析按钮&#xff0c;一个是gradle的&#xff0c;一般是后者是新安装的sbt。 选择需要分析的模块 只需要在project/plugins.sbt中添加代码&#xff0c;启动官方分析插件addDependencyTreeP…...

MySQL中事务特性以及隔离机制

目录 一、什么是事务 二、事务特性——即ACID特性 三、事务的隔离级别 1、脏读 2、不可重复读 3、幻读 Read uncommitted&#xff1a; Read committed: Repeatable read: Serializable&#xff1a; 一、什么是事务 事务&#xff08;Transaction&#xff09;——一个最…...

Docker知识(详细笔记)

概览图 文章目录 概览图docker 知识速查1. 初识 Docker1.1 概念1.2 特点1.3 架构1.4 应用场景1.5 安装 Docker1.6 配置 Docker 镜像 2. Docker 命令2.1 Docker 进程相关命令2.2 Docker 镜像相关命令2.3 Docker 容器相关命令 3. Docker 容器的数据卷3.1 数据卷概念及作用3.1.1 概…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)

旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据&#xff01;该数据集源自2025年4月发表于《地理学报》的论文成果…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!

今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等&#xff0c;设置经线、纬线都以10间隔显示。 2、需要插入背会归线&#xf…...

【题解-洛谷】P10480 可达性统计

题目&#xff1a;P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图&#xff0c;分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M&#xff0c;接下来 M M M 行每行两个整数 x , y x,y x,y&#xff0c;表示从 …...

联邦学习带宽资源分配

带宽资源分配是指在网络中如何合理分配有限的带宽资源&#xff0c;以满足各个通信任务和用户的需求&#xff0c;尤其是在多用户共享带宽的情况下&#xff0c;如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源&#xff0c;通常指的是单位时间…...

Three.js进阶之粒子系统(一)

一些特定模糊现象&#xff0c;经常使用粒子系统模拟&#xff0c;如火焰、爆炸等。Three.js提供了多种粒子系统&#xff0c;下面介绍粒子系统 一、Sprite粒子系统 使用场景&#xff1a;下雨、下雪、烟花 ce使用代码&#xff1a; var materialnew THRESS.SpriteMaterial();//…...

【AI教我写网站-ECG datacenter】

阶段性总结&#xff1a;后端用户管理基础 在项目管理和协作中&#xff0c;清晰地阐述“为什么做”比“怎么做”更能凝聚共识和提供方向。我们不仅要理解技术实现&#xff0c;更要明白其背后的动机和意义。 让我们重新回顾并总结我们到目前为止的工作&#xff0c;这次会更侧重…...

【鸿蒙在 ETS (Extendable TypeScript) 中创建多级目录或文件,可以使用鸿蒙的文件系统 API】

鸿蒙在 ETS (Extendable TypeScript) 中创建多级目录或文件&#xff0c;可以使用鸿蒙的文件系统 API。 // 导入需要的模块 import fs from ohos.file.fs;const TAG"Index" Entry Component struct Index {State message: string Hello World;build() {Row() {Colum…...

线性规划饮食问题求解:FastAPI作为服务端+libhv作为客户端实现

之前在 Pyomo介绍-CSDN博客 中介绍过通过Pyomo求解线性规划问题&#xff0c;这里使用FastAPI作为服务端&#xff0c;开源网络库libhv作为客户端&#xff0c;求解饮食成本最小化问题。 服务端测试代码test_fastapi_pyomo_server.py如下&#xff1a; from fastapi import FastAP…...