探索指针(4)-C语言

目录

1.回调函数

一.回调函数的基本概念

二.示例

三.详细说明

2.qsort使用举例

一.qsort 函数原型 

二.参数解释

三.比较函数

3.qsort函数的模拟实现

一.代码示例:

二.分段讲解代码 


1.回调函数

一.回调函数的基本概念

回调函数本质上是一种通过函数指针实现的机制。你可以定义一个函数指针,然后将其作为参数传递给另一个函数,当需要时调用该指针所指向的函数。

二.示例

以下是一个简单的示例,展示如何在C语言中使用回调函数。

  1. 定义一个函数类型(函数指针)和一个函数来调用回调函数。
  2. 定义实际的回调函数。
  3. 将回调函数传递给调用函数并执行。
#include <stdio.h>// 定义一个函数类型,表示一个接收两个int参数并返回int的函数
typedef int (*callback_t)(int, int);// 一个简单的加法函数,可以作为回调函数
int add(int a, int b) {return a + b;
}// 一个简单的减法函数,可以作为回调函数
int subtract(int a, int b) {return a - b;
}// 一个执行回调函数的函数
void execute_callback(callback_t callback, int x, int y) {int result = callback(x, y);printf("Result: %d\n", result);
}int main() {// 使用add函数作为回调函数execute_callback(add, 5, 3); // 输出: Result: 8// 使用subtract函数作为回调函数execute_callback(subtract, 5, 3); // 输出: Result: 2return 0;
}

三.详细说明

  1. 函数指针类型定义

 typedef int (*callback_t)(int, int)

 这里我们定义了一个新的类型 callback_t,它表示一个接收两个 int 参数并返回 int 的函数指针。

        2.回调函数的定义:    

int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}

我们定义了两个简单的函数 addsubtract,它们都符合 callback_t 类型。 

        3.调用回调函数的函数: 

void execute_callback(callback_t callback, int x, int y) {int result = callback(x, y);printf("Result: %d\n", result);
}

execute_callback 函数接收一个 callback_t 类型的回调函数和两个 int 参数,然后调用回调函数并打印结果。

        4.主函数中的调用:

int main() {execute_callback(add, 5, 3);execute_callback(subtract, 5, 3);return 0;
}

图文解释; 

2.qsort使用举例

qsort 是 C 标准库中用于对数组进行快速排序的函数。qsort 函数定义在 stdlib.h 头文件中,它可以对任意类型的数组进行排序,只需提供一个比较函数来确定元素的排序顺序。

一.qsort 函数原型 

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

二.参数解释

  • base:指向要排序的数组的起始地址。
  • nmemb:数组中的元素个数。
  • size:每个元素的大小(以字节为单位)。
  • compar:指向比较函数的指针,用于比较两个元素。

三.比较函数

比较函数接收两个 const void* 类型的参数,返回一个整数值:

  • 返回负值:如果第一个参数小于第二个参数。
  • 返回零:如果两个参数相等。
  • 返回正值:如果第一个参数大于第二个参数。 

以下是一个使用 qsort 对整数数组进行排序的示例:

#include <stdio.h>
#include <stdlib.h>// 比较函数,用于比较两个整数
int compare_ints(const void *a, const void *b) {int int_a = *(int *)a;int int_b = *(int *)b;if (int_a < int_b) return -1;else if (int_a == int_b) return 0;else return 1;
}int main() {int arr[] = {5, 2, 9, 1, 5, 6};size_t arr_size = sizeof(arr) / sizeof(arr[0]);// 使用qsort对数组进行排序qsort(arr, arr_size, sizeof(int), compare_ints);// 输出排序后的数组for (size_t i = 0; i < arr_size; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

 以下是一个对结构体数组进行排序的示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义一个结构体
typedef struct {char name[20];int age;
} Person;// 比较函数,用于比较两个Person结构体的年龄
int compare_persons(const void *a, const void *b) {Person *person_a = (Person *)a;Person *person_b = (Person *)b;return (person_a->age - person_b->age);
}int main() {Person people[] = {{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}};size_t people_size = sizeof(people) / sizeof(people[0]);// 使用qsort对结构体数组进行排序qsort(people, people_size, sizeof(Person), compare_persons);// 输出排序后的结构体数组for (size_t i = 0; i < people_size; i++) {printf("%s: %d\n", people[i].name, people[i].age);}return 0;
}

 在这个示例中,我们定义了一个 Person 结构体,并编写了一个比较函数 compare_persons,用于比较 Person 结构体的年龄。然后使用 qsort 对结构体数组按年龄进行排序。

3.qsort函数的模拟实现

一.代码示例:

#include <stdio.h>
#include <stdlib.h>//qsortint compare(const void* a, const void* b)
{if (*(int*)a < *(int*)b)return -1;if (*(int*)a == *(int*)b)return 0;if (*(int*)a > *(int*)b)return 1;
}void swap(char* a1, char* a2,int size)
{int i = 0;for (i = 0; i < size; i++){char tmp = 0;tmp = *a1;*a1 = *a2;*a2 = tmp;a1++;a2++;}
}
//qsort的模拟实现(使用冒泡排序)
void my_qsort(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 - i - 1; j++){if (compare((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[] = { 23,41,4,6,56,3,525,7,8,4,23,6 };int num = sizeof(arr) / sizeof(arr[0]);my_qsort(arr, num, sizeof(arr[0]), compare);int i = 0;for (i = 0; i < num; i++){printf("%d ", arr[i]);}return 0;
}

二.分段讲解代码 

比较函数:

int compare(const void* a, const void* b)
{if (*(int*)a < *(int*)b)return -1;if (*(int*)a == *(int*)b)return 0;if (*(int*)a > *(int*)b)return 1;
}
  • 这个函数用于比较两个整数。
  • 它接收两个 const void* 类型的参数,通过类型转换将它们转换为 int*,然后进行比较。
  • 根据比较结果返回负值、零或正值,分别表示第一个参数小于、等于或大于第二个参数。

交换函数 :

void swap(char* a1, char* a2, int size)
{int i = 0;for (i = 0; i < size; i++){char tmp = 0;tmp = *a1;*a1 = *a2;*a2 = tmp;a1++;a2++;}
}
  • 这个函数用于交换两个元素的内容。
  • 它接收两个 char* 类型的指针和一个 size 参数,表示元素的大小。
  • 通过循环逐字节地交换两个元素的内容。

 my_qsort 函数:

void my_qsort(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 - i - 1; j++){if (compare((char*)base + j * size, (char*)base + (j + 1) * size) > 0){swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}
  • 这个函数是 qsort 函数的模拟实现,使用冒泡排序算法对数组进行排序。
  • 参数说明:
    • base:指向要排序的数组的起始地址。
    • num:数组中的元素个数。
    • size:每个元素的大小(以字节为单位)。
    • compar:指向比较函数的指针,用于比较两个元素。
  • 外层循环控制排序的轮数,内层循环比较和交换相邻元素。
  • 使用 compare 函数比较相邻元素,如果需要交换,调用 swap 函数交换它们。

 

以上就是本次的所有内容,如果对你有所帮助,请不要吝啬你的点赞哦!

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

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

相关文章

将堆内存的最小值(Xms)与最大值(Xmx)设置为相同的配置,可以防止JVM在运行过程中根据需要动态调整堆内存大小

将堆内存的最小值&#xff08;Xms&#xff09;与最大值&#xff08;Xmx&#xff09;设置为相同的配置&#xff0c;可以防止JVM在运行过程中根据需要动态调整堆内存大小&#xff0c;从而避免因内存分配策略变化引起的性能波动&#xff0c;也就是所谓的"内存震荡"&…

RH442 开放研究实验: 选择性能监控工具

开放研究实验: 选择性能监控工具 任务执行清单 在本实验中&#xff0c;您将使用各种系统监控工具来观察系统表现。 成果 您应能够&#xff1a; 安装和配置 sysstat 软件包&#xff0c;以生成系统活动报告。安装和配置 Performance Co-Pilot&#xff0c;以采集原始数据来监…

流量攻击是什么意思?

对于多数的互联网企业都会受到流量攻击&#xff0c;那流量攻击是什么意思呢&#xff1f; 流量攻击一般是利用合理的服务请求来占用过多的服务器资源&#xff0c;从而导致正常合法的用户请求没有办法得到服务的响应&#xff0c;使服务无法进行正常的工作运行&#xff0c;流量攻击…

基于FreeRTOS+STM32CubeMX+LCD1602+MCP23S08(SPI接口)的I/O扩展器Proteus仿真

一、仿真原理图: 二、仿真效果: 三、STM32CubeMX配置: 1)、时钟配置: 2)、SPI配置: 四、部分软件: 1)、main主函数: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file :…

python实现CRC32计算

文章目录 计算法查表法测试验证 crc基础相关内容可参考&#xff1a; https://blog.csdn.net/xiaoyuanwuhui/article/details/131259671 计算法 # 将32位数据逆序排列 def reverse32(x):x (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1))x (((x &…

【7】ExternalCommand

文章目录 ExternalCommandProcessComponent(服务端)输入输出 external_command_demo&#xff08;客户端&#xff09;插件ActionCommandProcessor ExternalCommandProcessComponent(服务端) 输入 用户业务模块发送的命令为apollo::external_command::ExternalCommandProcessCo…

I2C bus,adaptor,client 在sysfs 的路径定位

i2c bus 路径 struct bus_type i2c_bus_type {.name "i2c",.match i2c_device_match,.probe i2c_device_probe,.remove i2c_device_remove,.shutdown i2c_device_shutdown, }; EXPORT_SYMBOL_GPL(i2c_bus_type);static int __init i2c_init(void) {int re…

使用ref定义响应式数据变量

Ref 使用 Ref 可以方便地创建和管理Vue组件中的响应式数据。例如&#xff0c;如果你有一个计数器组件&#xff0c;你可以使用 Ref 来创建一个响应式的计数器变量&#xff0c;然后在组件内部或外部修改这个变量的值&#xff0c;而不需要手动触发视图更新。 先声明一个变量&…

Adobe Photoshop 2024 v25.5.1 中文激活版下载以及安装方法教程

软件介绍 Adobe Photoshop 2024 v25.5.1 是Adobe公司的最新版图像处理软件&#xff0c;它提供了强大的图像编辑工具和智能自动化功能&#xff0c;包括图像修复、色彩校正和滤镜效果&#xff0c;以满足专业人士和业余爱好者的需求。这款软件还支持矢量图形设计和实时协作&#…

JavaScript之深入对象,详细讲讲构造函数与常见内置构造函数

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是前端菜鸟的自我修养&#xff01;今天给大家详细讲讲构造函数与常见内置构造函数&#xff0c;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;原创不易&#xff0c;如果能帮助到带大家&#xff0c;欢迎…

提升效率:快速绘制线框图的技巧

1、什么是线框 线框作为项目开始时的蓝图或示意图&#xff0c;可以帮助我们更清晰地向相关客户呈现相应的程序或网站的框架结构。从更深层次上讲&#xff0c;线框图代表了产品的基本设计布局&#xff0c;承载着界面显示的关键信息&#xff0c;绘制着要开发的应用程序或网站界面…

【NPU成为边缘智能新思路】

在人工智能&#xff08;AI&#xff09;技术日新月异的今天&#xff0c;从云端到边缘的计算需求不断攀升&#xff0c;为各行各业带来了前所未有的变革机遇。作为这一领域的领军者&#xff0c;Arm 公司凭借其卓越的节能技术和从云到边缘的广泛布局&#xff0c;正逐步构建着未来AI…

LeetCode题练习与总结:二叉树的后序遍历--145

一、题目描述 给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[3,2,1]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a…

AVR晶体管测试仪开源制作与验证

AVR晶体管测试仪开源制作与验证 &#x1f4cd;原项目地址&#xff1a;https://www.mikrocontroller.net/articles/AVR_Transistortester github地址&#xff1a;https://github.com/Mikrocontroller-net/transistortester &#x1f388;EasyEDA项目地址&#xff1a;https://osh…

《数据结构与算法基础 by王卓老师》学习笔记——2.4线性表的顺序表示和实现3

1.线性表的顺序存储表示 2.顺序表示意图 定义变量的时候才会分配空间&#xff0c;光有类型是不分配空间的 3.顺序表的基本操作 增删查三种较难&#xff0c;后面会讲 4.预定义常量和类型 5.算法一&#xff1a;线性表的初始化 6.线性表的几个简单操作 7.算法二&#xff1a;顺序…

鸿蒙自定义dialog弹窗及传参操作

第一步定义一个dialog&#xff1a; CustomDialog export struct InputDialog {controller: CustomDialogController;State counter: string "10";changeInputValue: Function (value: string) > {}build() {Column() {TextArea({ text: this.counter, placehol…

快速上手文心一言指令:解锁AI对话新纪元

快速上手文心一言指令 一、引言&#xff1a;文心一言的魅力所在二、准备工作&#xff1a;了解文心一言平台2.1 轻松注册&#xff0c;开启智能对话之旅2.2 深度探索&#xff0c;掌握界面布局奥秘2.2.1 输入框&#xff1a;智慧交流的起点2.2.2 回复区&#xff1a;即时反馈的窗口2…

IT行业入门,如何假期逆袭,实现抢跑

目录 前言 1.IT行业领域分类 2.基础课程预习指南 3.技术学习路线 4.学习资源推荐 结束语 前言 IT&#xff08;信息技术&#xff09;行业是一个非常广泛和多样化的领域&#xff0c;它包括了许多不同的专业领域和职业路径。如果要进军IT行业&#xff0c;我们应该要明确自己…

从一次 SQL 查询的全过程了解 DolphinDB 线程模型

1. 前言 DolphinDB 的线程模型较为复杂&#xff0c;写入与查询分布式表都可能需要多个类型的线程。通过了解 SQL 查询的全过程&#xff0c;可以帮助我们了解 DolphinDB 的线程模型&#xff0c;掌握 DolpinDB 的配置&#xff0c;以及优化系统性能的方法。 本教程以一个分布式 …

使用hadoop进行数据分析

Hadoop是一个开源框架&#xff0c;它允许分布式处理大数据集群上的大量数据。Hadoop由两个主要部分组成&#xff1a;HDFS&#xff08;Hadoop分布式文件系统&#xff09;和MapReduce。以下是使用Hadoop进行数据分析的基本步骤&#xff1a; 数据准备&#xff1a; 将数据存储在HDF…