指针修仙之实现qsort

server/2024/9/23 23:34:40/

文章目录

  • 回调函数
    • 什么是回调函数
    • 回调函数的作用
  • 库函数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/server/121040.html

相关文章

Day26_0.1基础学习MATLAB学习小技巧总结(26)——数据插值

利用空闲时间把碎片化的MATLAB知识重新系统的学习一遍&#xff0c;为了在这个过程中加深印象&#xff0c;也为了能够有所足迹&#xff0c;我会把自己的学习总结发在专栏中&#xff0c;以便学习交流。 参考书目&#xff1a; 1、《MATLAB基础教程 (第三版) (薛山)》 2、《MATL…

老挝语方言那么多,怎么沟通交流?可以用《老挝语翻译通》app

准备前往老挝探险&#xff0c;却担心语言不通&#xff1f;《老挝语翻译通》App来帮忙&#xff0c;专为老挝语学习者和旅行者设计&#xff0c;让你轻松掌握老挝语&#xff0c;无需打字&#xff0c;说话即可翻译。 应用特色&#xff1a; 中老互译&#xff1a;实时中文与老挝语互…

三菱FX5U CPU模块的初始化“(格式化PLC)”

1、连接FX5U PLC 1、使用以太网电缆连接计算机与CPU模块。 2、从工程工具的菜单选择[在线]中[当前连接目标]。 3、在“简易连接目标设置 Connection”画面中&#xff0c;在与CPU模块的直接连接方法中选择[以太网]。点击[通信测试]按钮&#xff0c;确认能否与CPU模块连接。 FX5…

《高等代数》范德蒙德行列式(应用)

说明&#xff1a;此文章用于本人复习巩固&#xff0c;如果也能帮助到大家那就更加有意义了。 注&#xff1a;1&#xff09;此题中的行列式是缺失了一行的范德蒙德行列式&#xff0c;解题思路是将其与范德蒙德行列式进行对比&#xff0c;我们将其添上一行和一列补成范德蒙德行列…

OpenAi assistant run always fails when called from PHP

题意&#xff1a;从 PHP 调用时&#xff0c;OpenAI 助理运行总是失败。 问题背景&#xff1a; The runs I create with the openai-php library fail direct in 100% of cases. What am I doing wrong? I do not have much experience with php but this is the test script.…

【Python报错已解决】ModuleNotFoundError: No module named ‘paddle‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

Python中使用Redis布隆过滤器

Python中使用Redis布隆过滤器 在Python中使用Redis布隆过滤器,可以利用 redis-py 库和 redis-py-bloom 扩展。布隆过滤器是一种空间效率高的概率性数据结构,适合用于判断某个元素是否在集合中。 以下是如何在Python中设置和使用Redis布隆过滤器的步骤: 安装依赖 首先,确…

C++ 简介

目录 面向对象程序设计 标准库 ANSI 标准 学习 C C 的使用 标准化 C 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言&#xff0c;支持过程化编程、面向对象编程和泛型编程。 C 被认为是一种中级语言&#xff0c;它综合了高级语言和低级语言的特点…