1. 回调函数

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

如果将函数指针作为参数传递给另一个函数,另一个函数根据指针来调这个函数,那么被调用的函数就是回调函数。回调函数不是由这个函数的实现方直接调用,而是在特定的条件下由另一方调用的。

例如在指针(3)中,我们将多个函数的地址放在函数指针数组中,根据不同的选择来对输入的x和y执行相应的计算,这里就是采用的就是回调函数的功能。

2. qsort使用举例

2.1 qsort函数

在 C 语言中,qsort是标准库<stdlib.h>提供的快速排序函数,用于对数组进行排序。其函数原型如下:

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

其中:

base是要排序的数组首元素的地址

nmemb是数组中元素的个数

size是每个元素的大小,单位为字节

compar是指比较函数的指针,用来定义排序规则

2.2 利用qsort函数排序整型数据

qsort会根据传递的函数指针所指向的那个函数的返回值来排序,例如两个值a,b进行比较:

当返回值为负时,a就会排在b前面;返回值为正时,a排在b后面;返回值为0时,qsort会将这两个值视为相等,但并不会保证相等元素排序与原始排序相同,例如:原始排序是 a  b,a在前,而qsort排序后可能会是b  a,即相等的元素排序后的相对位置不一定与原始位置相同。

知道这些我们可以利用qsort函数做一个简单的排序,让一个数组中的元素按升序排序:

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

我们可以看到输出结果与预期一致,qsort正确得进行了排序。

另外,我们可以看到我们定义的cmp函数中,在进行运算前前面先将指针p1与p2的类型先强制转换为了int *,这是因为void *虽然可以接受各种类型的指针,但是却不能直接使用,必须先进行强制类型转换。这里因为我们希望是升序,所以返回p1减去p2的值。若p1 < p2,返回值为负,p1排在p2前;若p1 > p2,返回值为正,p1排在p2后。如果我们想要实现降序,只需要将cmp函数体内p1与p2的位置互换或者是在计算表达式前加上 - ,改变正负即可。

2.3 使用qsort排序结构数据

现在我们尝试利用qsort函数来对结构数据进行排序,例如:

#include <stdio.h>
#include <stdlib.h>
int i;
struct Stu
{char name[10];int age;
};
int cmp_by_name(const void *p1,const void *p2)
{return strcmp(((struct Stu*)p1)->name,((struct Stu*)p2)->name);
}int main()
{struct Stu s[] = {{"zhangsan",20},{"lisi",23},{"wangwu",19}};int len = sizeof(s)/ sizeof(s[0]);int sz = sizeof(s[0]);qsort(s,len,sz,cmp_by_name);for(i = 0;i < len;i++){printf("%s\n",s[i].name);}return 0;
}
lisi
wangwu
zhangsan

根据打印结果,我们发现,qsort成功按照字母顺序进行了排序。同样的,我们也可以写出cmp_by_age函数,让qsort按照年龄来进行排序。

另外,我在定义函数cmp_by_name时,在函数体内部用 -> 来访问结构中的name,而在打印时使用的是 . 。这是因为,我在定义函数的返回值时,这里的数据是指针类型,只能用->来访问,而在打印时则是直接访问结构,所以要使用 . 来访问结构中数据。因此,如果我们不想使用->,也可以先对指针进行解引用操作然后再使用 . 来访问数据。

3. qsort函数的模拟实现

学习了qsort函数的使用方法后,我们现在尝试自己写代码来模拟实现qsort函数。

例如,我们用冒泡排序的方法法来模拟qsort函数。

那么。根据上面的代码的经验,我们可以得到下面的代码:

#include <stdio.h>int cmp(const void *p1,const void *p2)
{return (*(int*)p1 - *(int*)p2);
}
void swap(void *p1,void *p2,int sz)
{int i;char temp;for(i = 0;i < sz;i++){temp = *((char *)p1 + i);*((char *)p1 + i) = *((char *)p2 + i);*((char *)p2 + i) = temp;}
}void bubble(void* base,int num,int sz,int (*cmp)(const void *p1,const void *p2))
{int i,j;for(i = 0;i < num - 1;i++){for(j = 0;j < num - 1 - i;j++){if(cmp(base + j * sz,base + (j + 1) * sz) < 0){swap(base + j * sz,base + (j + 1) * sz,sz);}}}
}
int main()
{int i;int arr[] = {1,5,3,7,9,4,0,2,6,8};int num = sizeof(arr)/ sizeof(arr[0]);int sz = sizeof(arr[0]);bubble(arr,num,sz,cmp);for(i = 0;i < num;i++){printf("%d ",arr[i]);}return 0;
}
9 8 7 6 5 4 3 2 1 0 

这里主体的逻辑和上面的代码一样,值得一提的是swap这个函数。

在定义这个函数的时候我们是将指针类型强制转换为char * 类型,这样处理的好处是:我们为了模拟qsort函数实现通用设计,在不知道接受的数据类型的前提下,将指针类型强制转换为char *类型,而char *类型指针和 i 相加时只会跳过 i 个字节,这样能够充分交换每一个字节中的数据,防止遗漏,保证了数据的准确性。         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93062.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93062.shtml
英文地址,请注明出处:http://en.pswp.cn/web/93062.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue--video使用动态src时,视频不更新

问题描述 在 Vue项目中&#xff0c;尝试动态更新 标签的 元素 src 属性来切换视频时&#xff0c;遇到了一个问题&#xff1a;即使 src 已更改&#xff0c;浏览器仍不显示视频。 <template><video width"100%" height"100%" controlspause"…

计算机视觉--opencv(代码详细教程)(一)

在计算机视觉的广袤领域中&#xff0c;OpenCV 是一座极为关键的里程碑。无论是在前沿的学术研究&#xff0c;还是在蓬勃发展的工业界&#xff0c;OpenCV 凭借其强大的功能与高效的性能&#xff0c;为开发者提供了丰富的图像处理和计算机视觉算法&#xff0c;助力无数项目落地。…

物联网通讯协议-MQTT、Modbus、OPC

引言在物联网迅速发展的今天&#xff0c;设备间的通信协议扮演着至关重要的角色。它们是不同设备、系统之间实现数据交换的桥梁。本文将详细介绍三种在物联网领域广泛应用的通讯协议——MQTT、Modbus和OPC&#xff0c;包括它们的基础概念、特点及在C#中的实现方法。一、MQTT协议…

牛客周赛R104 小红的矩阵不动点

D-小红的矩阵不动点_牛客周赛 Round 104 赛时这道题卡了一段时间&#xff0c;赛时代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int ans,h; int a[505][505]; signed main(){ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);int n,m;cin>…

Rust面试题及详细答案120道(19-26)-- 所有权与借用

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Jenkins + SonarQube 从原理到实战三:SonarQube 打通 Windows AD(LDAP)认证与踩坑记录

前言 在前两篇文章中&#xff0c;已经介绍了 SonarQube 的部署 以及 通过 sonar-cxx 插件实现 C/C 代码扫描。 本篇将重点讲 如何让 SonarQube 对接 Windows AD&#xff08;LDAP&#xff09;&#xff0c;实现域账号登录和基于 AD 组的权限管理。 一、背景与需求分析 需求分析…

[AI React Web] 包与依赖管理 | `axios`库 | `framer-motion`库

第七章&#xff1a;包与依赖管理 在我们使用open-lovable的旅程中&#xff0c;已经探索了它如何管理对话状态&#xff08;第一章&#xff1a;对话状态管理&#xff09;、将创意转化为可运行代码&#xff08;第二章&#xff1a;AI代码生成管道&#xff09;、如何在安全的虚拟环…

PanSou 一款开源网盘搜索项目,集成前后端,一键部署,开箱即用

PanSou 网盘搜索API PanSou是一个高性能的网盘资源搜索API服务&#xff0c;支持TG搜索和自定义插件搜索。系统设计以性能和可扩展性为核心&#xff0c;支持并发搜索、结果智能排序和网盘类型分类。 项目地址&#xff1a;https://github.com/fish2018/pansou 特性&#xff08…

java爬虫实战

本人目前在做鱼皮的《智能协同云图库》&#xff0c;涉及到了以图搜图图片爬取&#xff0c;虽然以前有爬过图片&#xff0c;但是用的都是别人现成的代码&#xff0c;不怎么去理解为什么要这样做&#xff0c;这次有在尝试理解每一个步骤。本人基础极差&#xff0c;属于一点基础也…

深入详解C语言的循环结构:while循环、do-while循环、for循环,结合实例,讲透C语言的循环结构

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、C/C干货分享&学习过程记录 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#…

北京-4年功能测试2年空窗-报培训班学测开-第七十四天-线下面试-聊的很满意但可能有风险-等信吧

今天没去教室&#xff0c;因为下午有个线下面试。其实是可以去教室的&#xff0c;但我实在太焦虑了&#xff0c;我觉得去了教室我心情会更不好&#xff0c;什么都干不下去&#xff0c;所以我选择不去早上依旧是带着满满焦虑起来的&#xff0c;会觉得自己的一切都不令自己满意&a…

在ubuntu服务器下安装cuda和cudnn(笔记)

目录 0 引言 1 相关环境查询 2 安装cuda 2.1 下载并安装 2.2 安装选项配置 2.3 验证安装 3 安装cudnn 3.1 下载 3.2 解压 3.3 删除旧版本 cuDNN 3.4 复制新文件到 CUDA 目录 3.5 设置文件权限 3.6 创建软链接 3.7 验证安装 0 引言 我在使用服务器的cuda11.8的时…

docker安装centos

docker库地址https://hub.docker.com/ 尝试使用centos7试了几次超时 换了个版本就可以了 docker pull centos:centos7.9.2009有时候需要更新资源地址 可以使用 vim /etc/docker/daemon.json配置其他资源地址 {"registry-mirrors": ["http://hub-mirror.c.163…

内容索引之word转md工具 - markitdown

切分文档构建RAG库过程中&#xff0c;langchain、llamaindex更期望处理latex、md类带有显式结构文档。 langchain、llamaindex切分word&#xff0c;有可能将段落中间截断&#xff0c;导致切分后的块语义不完整。 所以&#xff0c;需要先将word转化为md格式&#xff0c;然后再…

MaxKB+合合信息TextIn:通过API实现PDF扫描件的文档审核

上海合合信息科技股份有限公司&#xff08;以下简称为合合信息&#xff09;是一家深耕人工智能、OCR&#xff08;光学字符识别&#xff09;及商业大数据技术领域的科技企业。该公司拥有领先的智能文字识别技术&#xff0c;其名片全能王&#xff08;CamCard&#xff09;、扫描全…

MyBatis 核心入门:从概念到实战,一篇掌握简单增删改查

目录 一、什么是 MyBatis&#xff1f;为什么要用它&#xff1f; 二、MyBatis 核心概念&#xff08;通俗理解&#xff09; 1.SqlSessionFactory 2.SqlSession 3.Mapper接口 4.映射文件&#xff08;XML&#xff09; 三、手把手搭建第一个 MyBatis 项目 1. 准备工作 2. 核心配置文…

数据结构初阶(12)排序算法—插入排序(插入、希尔)(动图演示)

2. 常见排序算法的实现2.0 十大排序算法2.1 插入排序 2.1.1 基本思想直接插入排序是一种简单的插入排序法&#xff1a;基本思想把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中。直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。 比 挪 (…

MySQL优化常用的几个方法

本实例是对慢sql从2万优化到5千优化方法的汇总。 首先贴上优化效果&#xff1a;1、更新数据时使用ID更新&#xff1b;2、"分页/轮询"查询时先获取符合数据要求主键的最大和最小ID&#xff0c;然后WHERE条件增加ID步增查询&#xff1b;3、检查SQL是否命中WHERE条件&am…

深入解析 AUTOSAR:汽车软件开发的革命性架构

引言在汽车智能化、网联化、电动化浪潮席卷全球的今天&#xff0c;汽车电子系统的复杂性与日俱增。传统“烟囱式”的 ECU 开发模式&#xff08;各供应商独立开发软硬件&#xff09;带来了巨大的兼容性、复用性和维护成本挑战。AUTOSAR&#xff08;AUTomotive Open System ARchi…

计算机视觉(opencv)实战一——图像本质、数字矩阵、RGB + 图片基本操作(灰度、裁剪、替换等)

OpenCV 入门教程&#xff1a; OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;广泛应用于图像处理、视频分析、机器学习等领域。 在 Python 中&#xff0c;cv2 是 OpenCV 的主要接口模块。本文将带你一步步掌握 cv2…