深入解剖指针(4)

news2024/9/28 9:27:41

个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客

目录

回调函数

qsort使用举例

使用qsort函数排序整型数据 

使用qsort排序结构数据 

qsort函数的模拟实现 


 

回调函数

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

简单来说就是:当我拥有一个函数(地址)指针时,在一些特定的情况下,通过函数指针回过头来调用这个函数,那么这个被调用的函数就是回调函数。

在简易计算器的制作(函数指针数组的实践)-CSDN博客这篇文章中写的计算代码,就是可以用这个回调函数的例子。如果我们要使用加法计算两个数的值,不是直接由main函调用的,而是由calc函数来调用对应的加法函数。这便是回调函数。

qsort使用举例

使用qsort函数排序整型数据 

如果我们想要排序一组数据,按照升序或者降序的方式,首先想到的就是冒泡排序。这个排序在深入解剖指针篇(2)-CSDN博客 这篇文章中介绍了。核心思想就是:两两相邻元素的比较。

我们现在就用qsort函数来实现。首先,就得了解什么是qsort函数。

上面就是关于qsort函数的基本介绍。

void qsort(void* base, //这个base就是要排序的元素的起始地址
		   size_t num, //这个num就是要排序的元素个数
		   size_t size,//这个size就是要排序的元素对应字节数
		   int (*compar)(const void*, const void*));//这个其实就是一个 有比较功能函数 的指针

上面那个比较功能就是你要怎么实现这个排序,就用什么功能。例如:我要实现升序功能,那么这个函数就是实现升序的功能。 

我们现在就可以开始模拟实现冒泡排序了。

#include <stdio.h>
#include <stdlib.h>//qsort函数所需的头文件

//打印数据看看是否排序成功
void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

//调用的排序函数
//由于创造这个函数的人,不知道我们会比较什么样的数据,因此,就要void*来接收。
int int_cmp(const void* p1, const void* p2)
{
    //qsort默认的是升序,由于void*不能直接解引用,所以就先得强制转换为要比较(int*)的数据类型
	return (*(int*)p1 - *(int*)p2);//如果我们像排成降序,就可以把这个给反过来
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), int_cmp);
	Print(arr, sz);
	return 0;
}

可以看出来这个qsort函数排序是正确的。

使用qsort排序结构数据 

我们假设要排序一些不是整型的数据,那么冒泡排序肯定是不行的。但是我们可以采用其思想,来进行排序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu//创建一个结构体类型:学生
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}

void Print(struct stu* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", (p+i)->name);//结构体指针->成员名
	}
	printf("\n");
}
int main()
{
    //创建一个结构体数组并且初始化
	struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
	Print(arr, sz);
	return 0;
}

 strcmp是用来比较字符串大小的,具体用法请看:字符函数与字符串函数(上)-CSDN博客 

通过上面的学习,我们就可以发现这个qsort函数在使用时,需要我们根据自己的需求来写出对应的比较函数。

结构体成员的间接访问 

我们在访问结构体成员时,有两种操作符,一种是 . (直接访问),还有一种是 ->(间接访问)。

直接访问在操作符详解(下)-CSDN博客 里讲过。

结构体指针->成员名 ,即当 -> 的左边满足时结构体指针时,我们要访问结构体成员就可以用->。 

上面是排序其名字,我们还可以排序其年龄

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return (((struct stu*)e1)->age - ((struct stu*)e2)->age);
}

void Print(struct stu* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", (p + i)->age);
	}
	printf("\n");
}

int main()
{
	struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
	Print(arr, sz);
	return 0;
}

qsort函数的模拟实现 

我们现在就来通过模拟实现qsort函数(用冒泡的方式)来排序整形数组。

#include <stdio.h>
int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

//因为前面有强制转换为char*了,所以我们也就不用void*了
void Swap(char* p1, char* p2, size_t width)
{
	//如果是排序char的数据,我们就只能一个字节一个字节的交换
	for (int i = 0; i < width; i++)
	{
		char tmp = *(p1+i);
		*(p1+i) = *(p2+i);
		*(p2+i) = tmp;
	}
}

void bubble_sort(void* base, size_t num, size_t width, int(*cmp)(void*, void*))
{
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			//如果前者大于后者,也就是降序,会返回一个大于0的数(根据这个cmp的函数来的)
			//不知道是啥类型,强制转换为最小的就行(类型占字节最小的是字符型)
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);//采用冒泡的方式
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java-幂等性

幂等性 1.1幂等性定义&#xff1a; 在计算机领域中&#xff0c;幂等&#xff08;Idempotence&#xff09;是指任意一个操作的多次执行总是能获得相同的结果&#xff0c;不会对系统状态产生额外影响。在Java后端开发中&#xff0c;幂等性的实现通常通过确保方法或服务调用的结…

68-解构赋值,迭代器,生成器函数,Symbol

1.解构赋值(针对数组array&#xff0c;字符串String及对象object以) 结构赋值是一种特殊的语法&#xff0c;通过将各种结构中的元素复制到变量中达到"解构"的目的&#xff0c;但是数组本身没有改变 1.1解构单层数组 <script>let arr [1,2,3,4,5];//获取数组…

C++之queue和deque

1、queue queue&#xff08;队列&#xff09;&#xff0c;一种数据结构&#xff0c;可以让某些数据结构的操作变得简单。队列&#xff08;queue&#xff09;最大的特点就是先进先出。就是说先放入queue容器的元素一定是要先出队列之后&#xff0c;比它后进入队列的元素才能够出…

【python】遵守 robots.txt 规则的数据爬虫程序

程序1 编写一个遵守 robots.txt 规则的数据爬虫程序涉及到多个步骤&#xff0c;包括请求网页、解析 robots.txt 文件、扫描网页内容、存储数据以及处理异常。由于编程语言众多&#xff0c;且每种语言编写爬虫程序的方式可能有所不同&#xff0c;以下将使用 Python 语言举例&am…

Material UI 5 学习01-按钮组件

Material UI 5 学习01-按钮组件 一、安装Material UI二、 组件1、Button组件1、基础按钮2、variant属性3、禁用按钮4、可跳转的按钮5、disableElevation属性6、按钮的点击事件onClick 2、Button按钮的颜色和尺寸1、Button按钮的颜色2、按钮自定义颜色3、Button按钮的尺寸 3、图…

Topaz Gigapixel AI:让每一张照片都焕发新生mac/win版

Topaz Gigapixel AI 是一款革命性的图像增强软件&#xff0c;它利用先进的人工智能技术&#xff0c;能够显著提升图像的分辨率和质量。无论是摄影爱好者还是专业摄影师&#xff0c;这款软件都能帮助他们将模糊的、低分辨率的照片转化为清晰、细腻的高分辨率图像。 Topaz Gigap…

每日五道java面试题之mysql数据库篇(三)

目录&#xff1a; 第一题. 百万级别或以上的数据如何删除&#xff1f;第二题. 前缀索引第三题. 什么是最左前缀原则&#xff1f;什么是最左匹配原则?第四题. B树和B树的区别第五题. 使用B树和B树好处 第一题. 百万级别或以上的数据如何删除&#xff1f; 关于索引&#xff1a;…

【微服务】微服务中常用认证加密方案总结

目录 一、前言 二、登录认证安全问题 3.1 认证方式选择 三、常用的加密方案 3.1 MD5加密算法 3.1.1 md5特点 3.1.2 md5原理 3.1.3 md5使用场景 3.2 AES加密算法 3.2.1 AES简介 3.2.2 AES加解原理 3.2.3 AES算法优缺点 3.2.4 AES算法使用场景 3.3 RSA加密算法 3.3…

【IDEA+通义灵码插件】实现属于你的大模型编程助手

目录 1.前言 2.下载安装 3.解释代码 4.生成单元测试 5.生成注释 6.智能补全 1.前言 大模型到底该以一种什么方式落地&#xff0c;从而嵌入我们的工作当中&#xff0c;助力我们工作效率的提升&#xff0c;其实最好的方式也许就是虚拟助手的方式&#xff0c;就像钢铁侠的&…

无极低码:无极低码部署版操作指南

无极低码 &#xff1a;https://wheart.cn 无极低码是一个面向开发者的工具&#xff0c;旨在为开发者、创业者或研发企业&#xff0c;提供快速&#xff0c;高效&#xff0c;标准化&#xff0c;可定制&#xff0c;私有化部署的平台&#xff0c;在兼顾开发速度的同时&#xff0c;兼…

ChemDraw Pro 2022:呈现专业化学绘图的极 致之作 mac/win版

PerkinElmer ChemDraw Pro 2022是一款功能强大的化学绘图软件&#xff0c;专为化学家、科研工作者和教育者设计。这款软件凭借其卓越的性能和丰富的功能&#xff0c;已经成为化学绘图领域的领导者。 PerkinElmer ChemDraw Pro 2022软件获取 ChemDraw Pro 2022提供了广泛的化学…

可重入锁-隐式锁与显式锁

可重入锁 隐式锁&#xff08;即synchronized关键字使用的锁&#xff09;&#xff0c;默认是可重入锁 在一个synchronized修饰的方法或者代码块的内部调用本类的其他synchronized修饰的方法或者代码块时&#xff0c;是永远可以得到锁。 显式锁&#xff08;即Lock&#xff09;也…

【yolov8部署实战】VS2019环境下使用Onnxruntime环境部署yolov8目标检测|含源码

一、前言 部署yolo项目&#xff0c;是我这几个月以来做的事情&#xff0c;最近打算把这几个月试过的方法&#xff0c;踩过的坑&#xff0c;以博客的形式&#xff0c;分享一下。关于下面动态中讲到的如何用opencv部署&#xff0c;我在上一篇博客中已经详细讲到了&#xff1a;【…

【C++】const成员

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. const成员3. 取地址及const取地址操作符重载 1. 前言 在之前已经已经分享过了关于 【C】类和对象之常引用与运算符重载&#xff0c;这次分享的有关const的内容&#xff0c;话不多说&#xff0c;正文开始。…

Mybatis 框架 基础语法

Mybtais 中文网站 Maven 仓库 考点&#xff1a; SQL 注入 #{}最终生成预编译sql&#xff0c;预编译Sql语句中?替换#{}内容 一个#{} 替换一个? 在模糊查询时要使用 &#xff0c; ′ {}&#xff0c;% &#xff0c;′{}%’ &#xff0c;因为&#xff1f;不能出现在‘’中&…

2024最新算法:鹦鹉优化算法(Parrot optimizer,PO)求解23个基准函数

一、鹦鹉优化算法 鹦鹉优化算法&#xff08;Parrot optimizer&#xff0c;PO&#xff09;由Junbo Lian等人于2024年提出的一种高效的元启发式算法&#xff0c;该算法从驯养的鹦鹉中观察到的觅食、停留、交流和对陌生人行为的恐惧中汲取灵感。这些行为被封装在四个不同的公式中…

2024年自动化测试五大趋势

目录 2024年QA自动化趋势&#xff1a;塑造软件开发的未来 1.自动化测试中的AI和ML集成 2.DevOps中的持续测试 3.无代码自动化工具的使用 4.更加重视安全测试 5.定制化测试解决方案 有效实施2024年QA自动化趋势 1.集成AI和ML实现更智能的测试 2.在敏捷和DevOps文化中嵌入…

5.STL源码解析-算法、仿函数、适配器

算法 STL算法总览 仿函数与适配器 C标准模板库&#xff08;STL&#xff09;是C程序员的得力工具&#xff0c;提供了许多强大而高效的数据结构和算法。在STL中&#xff0c;仿函数&#xff08;Functor&#xff09;和适配器&#xff08;Adapter&#xff09;是两个重要的概念…

windows上elasticsearch的ik分词器的安装

下载 下载地址 在elasticsearch下的plugins文件夹下创建ik的文件夹 下载的ik压缩包解压到plugins/ik 重启elasticsearch 验证 http://ip:9200/_cat/plugins

OSCP靶场--Squid

OSCP靶场–Squid 考点(1.squid代理绕过 2.phpmyadmin写webshell 3.受限服务账户【LOCAL SERVICE或NETWORK SERVICE】恢复特权 4.SeImpersonatePrivilege提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.188.189 --min-rate 2000 Starti…