指针修仙之实现qsort

embedded/2024/9/23 22:53:05/

文章目录

  • 回调函数
    • 什么是回调函数
    • 回调函数的作用
  • 库函数qsort
    • 使用qsort函数排序整形
    • 使用qsort函数排序结构体
  • qsort函数模拟实现
    • 说明
    • 源码`and`说明


回调函数

什么是回调函数

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

回调函数的作用

回调函数可以减少函数的冗余,并且可以使函数的功能更加丰富,实现泛型编程,我们之间从下面qsort的模拟实现中体会

库函数qsort

我们看一下qsort的官方描述
在这里插入图片描述
分析以下函数的参数,依次是:

  1. 数组首元素地址
  2. 数组元素个数
  3. 数组元素大小
  4. 自定义比较函数的地址

使用qsort函数排序整形

int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
int main()
{int arr[] = { 2,4,3,5,9,8,6,7,1,0 };qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp_int);return 0;
}

注意 自定义比较函数的参数类型是void*,要先将地址强制类型转换成int*再解引用

使用qsort函数排序结构体

#include<string.h>
int cmp_stu_by_age(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
struct Stu
{char name[10];int age;
};
int main()
{struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}

注意 比较字符串时要用库函数strcmp

qsort函数模拟实现

说明

回顾我这个编程小白的排序技能库,似乎只会一种冒泡排序,所以下面模拟实现qsort是在冒泡排序的基础上改进完成的

源码and说明

主体部分

void bubble_sort_plus(void* base, size_t num, size_t size, void* cmp(const void*, const void*))
{for (int i = 0; i < num-1; i++){for (int j = 0; j < num - i - 1; j++){if (cmp((char*)base + j*size, (char*)base + (j+1)*size) > 0){Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}

注意

  • 函数参数和库函数中的qsort类型相同
  • 内层循环的判断条件
    • 通过地址来调用用户自定义的比较函数,自定义的比较函数的参数,强制转换成char* 找到元素第 一个字节的地址,然后再加上每一个元素的宽度,即可访问数组中的元素
    • 使用函数地址来调用函数,cmp函数是一个回调函数,使用户自定义函数类型,丰富了函数的功能
  • 实现交换功能
    • 由于不知道用户传递来的函数数据类型,因此只能先强制转换为char*类型的数据,通过一个一个的字节来访问元素

Swap函数

void Swap(char* p1, char* p2, size_t size)
{for (int i = 0; i < size; i++){char tmp = *p1;*p1 = *p2;*p2 = tmp;p1++;p2++;}
}

注意

  • 函数参数直接用char*类型来接收
  • 设计参数size,可以控制交换字节的个数
  • 交换的原理是一个字节一个字节的交换


http://www.ppmy.cn/embedded/115797.html

相关文章

如何进入电脑BIOS

前言 在日常使用电脑的过程中&#xff0c;有时我们需要进入BIOS&#xff08;基本输入输出系统&#xff09;来调整设置&#xff0c;比如更改启动顺序、调整系统日期时间或是优化硬件配置。BIOS是计算机启动时最先运行的程序之一&#xff0c;它位于主板上的一个ROM芯片中。下面&…

【监控】【Nginx】使用 Prometheus + Grafana 监控 Nginx

目录 一、什么是 Prometheus 和 Grafana&#xff1f;二 、准备工作步骤 1&#xff1a;安装 Prometheus1. 下载并解压 Prometheus2. 编辑 Prometheus 配置&#xff08;prometheus.yml&#xff09;3. 启动 Prometheus 步骤 2&#xff1a;安装 Grafana1. 安装 Grafana2. 启动 Graf…

Python ORM 框架 SQLModel 快速入门教程

创建模型 import sqlmodel import typingclass Hero(sqlmodel.SQLModel, tableTrue):id: typing.Optional[int] sqlmodel.Field(defaultNone, primary_keyTrue)name: strreal_name: strage: typing.Optional[int] None创建表 import sqlmodel import typingclass Hero(sqlm…

win11 此应用无法在你的电脑上运行 若要找到适用于你的电脑的版本,请咨询软件发布者

在Windows 11上遇到“此应用无法在你的电脑上运行”的问题&#xff0c;通常意味着该应用程序与Windows 11不兼容&#xff0c;或者你的系统设置阻止了应用程序的运行。以下是一些解决这个问题的步骤&#xff1a; 操作系统不支持 某些应用程序可能尚未更新以支持Windows 11&…

人工智能学习思路(新生新手小白的指引手册-超详细版)

一、前言 该内容仅作为个人笔记使用&#xff0c;希望看到的各位能有所获&#xff0c;博主有误的地方&#xff0c;各位可以在评论区有所指正 二、正文 1、0基础小白&#xff08;连计算机是啥都不知道&#xff09; 首先对于计算机这块都没怎么涉猎的新生来说&#xff0c;首先…

Linux入门学习:Git

文章目录 1. 创建仓库2. 仓库克隆3. 上传文件4. 相关问题4.1 git进程阻塞4.2 git log4.3 上传的三个步骤在做什么4.4 配置邮箱/用户名 本文介绍如何在Linux操作系统下简单使用git&#xff0c;对自己的代码进行云端保存。 1. 创建仓库 &#x1f539;这里演示gitee的仓库创建。…

一.Oracle每日运维操作

目录 一&#xff0e;Oreace每日运维操作 1.1、确认所有的INSTANCE状态正常 1.2、检查文件系统的使用&#xff08;剩余空间&#xff09; 1.3 lwh暗码&#xff0c;&#xff0c;、检查日志文件和trace文件记录 1.4 lwh、检查数据库当日备份的有效性。 1.5、检查数据文件的状…

【STM32系统】基于STM32设计的智能垃圾桶(语音、颜色识别、称重、光强、烟雾、人体识别、步进电机、水泵)——文末资料下载

基于STM32设计的智能垃圾桶 演示视频: 基于STM32设计的智能垃圾桶 功能简介: 四个按键可分别打开四个垃圾桶(可回收垃圾、厨余垃圾、有害垃圾、其他垃圾) oled显示屏显示四个垃圾桶的打开/关闭状态、烟雾浓度、光照强度、称重的重量和识别到的颜色(白色、红色、绿色、蓝…