第十二讲:指针(4)

news2024/10/6 8:27:35

第十二讲:指针(4)

  • 1.回调函数
    • 1.1什么是回调函数
    • 1.2深入理解并使用回调函数
      • 1.2.1简单写法
      • 1.2.2优化
  • 2.qsort函数详解
    • 2.1函数简单介绍
    • 2.3qsort函数使用举例
      • 2.3.1qsort函数排序整形数据
      • 2.3.2qsort函数排序结构数据
  • 3.qsort函数的模拟实现
    • 3.1冒泡排序
    • 3.2冒泡排序的改造

总结:该篇博客详细对以下两个内容进行讲解:
1.回调函数
2.qsort函数

1.回调函数

1.1什么是回调函数

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

如果我们将函数的地址作为参数传递给另一个函数,当通过这个指针被用来调用其指向的函数时,被调用的函数就是回调函数,回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应
下面我们通过代码来理解什么是回调函数:

1.2深入理解并使用回调函数

我们写一个简易的计算器

1.2.1简单写法


int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

这个方法写的十分冗余,下面我们来进行优化

1.2.2优化


int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}

void calc(int (*pa)(int, int)) //使用函数指针变量来接受函数指针
{
	printf("请输入两个操作数:\n");
	int x, y;
	x = 0;
	y = 0;
	scanf("%d %d", &x, &y);
	int set = pa(x, y);
	printf("%d\n", set);
}

int main()
{
	int input = 1;
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(add);  //将想要使用的函数的地址传入,用于调用
			break;
		case 2:
			calc(sub);
			break;
		case 3:
			calc(mul);
			break;
		case 4:
			calc(div);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

我们通过画图来理解回调函数:
在这里插入图片描述

在这里插入图片描述

2.qsort函数详解

2.1函数简单介绍

这是一个执行快速排序的函数,包含在<stdlib.h>库中

函数原型:


void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

对各个参数进行介绍如下:

1.base:指向要排序数组的首元素的地址
2.num:数组中的元素的个数
3.width:数组中每个元素的大小,单位是字节
4.int (__cdecl *compare )(const void *elem1, const void *elem2 ):
这是一个由编程者自己写的函数,将函数地址传入,函数的形式被规定,该函数定义了如何比较两个元素

对于自己定义的这个函数,通过其返回值决定所排序元素的顺序,遵循以下原则 :
在这里插入图片描述

2.3qsort函数使用举例

2.3.1qsort函数排序整形数据


//使⽤qsort函数排序整型数据

int Sort1(const void* pa, const void* pb)
{
	return (*(int *)pa - *(int*)pb);
}

int main()
{
	int arr[] = { 2,3,4,5,1,6,7,9,10 };

	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), Sort1); //void qsort(void* base, 
	        //size_t num, 
			//size_t width, 
			//int(__cdecl * compare)(const void* elem1, const void* elem2));
	Print(arr, sz);
	return 0;
}

2.3.2qsort函数排序结构数据


//使⽤qsort函数排序结构数据

//创建一个结构类型,假设为学生数据
struct Stu
{
	char name[20];
	int age;
};

//按照名字排序
int SortByName(const void* pa, const void* pb)
{
	return (strcmp(((struct Stu*)pa)->name, ((struct Stu*)pb)->name));
}

//按照年龄排序
int SortByAge(const void* pa, const void* pb)
{
	return (((struct Stu*)pa)->age - ((struct Stu*)pb)->age);
}

int main()
{
	//给定学生数据
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };

	int sz = sizeof(arr) / sizeof(arr[0]);
	//按照名字排序
	qsort(arr, sz, sizeof(arr[0]), SortByName); //void qsort(void* base, 
										   //size_t num, 
										   //size_t width, 
										   //int(__cdecl * compare)(const void* elem1, const void* elem2));
	//按照年龄排序
	qsort(arr, sz, sizeof(arr[0]), SortByAge); //void qsort(void* base, 
									       //size_t num, 
										   //size_t width, 
										   //int(__cdecl * compare)(const void* elem1, const void* elem2));

	return 0;
}

3.qsort函数的模拟实现

我们使用冒泡排序来进行qsort函数的模拟实现,首先先介绍一下什么是冒泡排序

3.1冒泡排序

目前的排序方式有很多,快速排序,希尔排序,冒泡排序,我们现在使用冒泡排序进行类比排序


void BubbleSort(int* pa, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (*(pa + j) > *(pa + j + 1))
			{
				int temp = *(pa + j);
				*(pa + j) = *(pa + 1 + j);
				*(pa + 1 + j) = temp;
			}
		}
	}
}

void Print(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", *(arr + i));
}

int main()
{
	int arr[] = { 2,3,4,5,1,6,7,9,10 };

	//冒泡排序
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz);

	//进行打印
	Print(arr, sz);
	return 0;
}

3.2冒泡排序的改造


//冒泡函数的改造
void Change(char* pa, char* pb, int sz)
{
	for(int i = 0; i<sz; i++)
	{
		char temp = *pa;
		*pa = *pb;
		*pb = temp;
		pa++;
		pb++;
	}
}

void BubbleSort(void* pa, size_t sz, size_t width, int(* compare)(const void* pa, const void* pb))
{
	for (int i = 0; i < sz - 1; i++)  //尽管是改造,但是这两个for循环是不用改变的
	{                                 //第一个for循环表示循环次数
		for (int j = 0; j < sz - 1 - i; j++) //第二个for循环是将两个数进行比较
		{
			//仍然是判断,如果compare函数返回值大于0,进行交换
			if (compare((char*)pa + j * width, (char*)pa + (j + 1) * width) > 0)
				Change((char*)pa + j * width, (char*)pa + (j + 1) * width, width); //进行交换,但是这个交换一次要交换数组类型个字节
		}
	}
}

int main()
{
	//给定学生数据
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };

	//冒泡排序
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz, sizeof(arr[0]), SortByName);  //void qsort(void* base, 
										              //size_t num, 
										              //size_t width, 
										              //int(__cdecl * compare)(const void* elem1, const void* elem2));
	BubbleSort(arr, sz, sizeof(arr[0]), SortByAge);
	return 0;
}

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

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

相关文章

网络实验新境界,PNETLab模拟器部署指南

在网络工程领域&#xff0c;拥有一个可靠的网络实验平台至关重要。PNETLab模拟器是一款功能强大的网络仿真工具&#xff0c;它支持包括华为、华三、锐捷、思科在内的多种设备&#xff0c;并且以开源免费的形式提供&#xff0c;这使得它在业界备受青睐。 软件介绍 PNETLab&am…

ThingsBoard版本控制配合Gitee实现版本控制

1、概述 2、架构 3、导出设置 4、仓库 5、同步策略 6、扩展 7、案例 7.1、首先需要在Giitee上创建对应同步到仓库地址 ​7.2、giit仓库只能在租户层面进行配置 7.3、 配置完成后&#xff1a;检查访问权限。显示已成功验证仓库访问&#xff01;表示配置成功 7.4、添加设…

【代码随想录】【动态规划】背包问题 - 完全背包

完全背包 模板&#xff1a;完全背包问题 问题描述 完全背包问题与01背包问题唯一的区别在于&#xff1a; 在01背包中&#xff1a;每个物品只有一个&#xff0c;要么放入背包&#xff0c;要么不放入背包在完全背包中&#xff1a;每个物品有无限多个&#xff0c;可以不放入背…

使用Eigen将经纬度、高程、偏北角转成变换矩阵

目录 1、前言 2、示例 3、代码解析 4、垂直于给定点的切平面变换 5、代码解析 1、前言 在地球表面进行刚体变换时候&#xff0c;要将具有经纬度、高程和偏北角的坐标信息转换为变换矩阵表达&#xff0c;首先需要了解坐标系之间的转换关系。 通常&#xff0c;我们会将经纬…

C++进阶:哈希(1)

目录 1. 简介unordered_set与unordered_map2. 哈希表&#xff08;散列&#xff09;2.1 哈希表的引入2.2 闭散列的除留余数法2.2.1 前置知识补充与描述2.2.2 闭散列哈希表实现 2.3 开散列的哈希桶2.3.1 结构描述2.3.2 开散列哈希桶实现2.3.3 哈希桶的迭代器与key值处理仿函数 3.…

第五届电子通讯与人工智能学术会议(ICECAI 2024, 5/31-6/2)

目录 1. 会议官方2. 会议新闻中华人民共和国教育部新闻 3. 出版历史4. 大会简介5. 主办单位与嘉宾主办单位承办单位主讲嘉宾组委会 6. 征稿主题7. 论文出版8. 参会说明 1. 会议官方 2024 5th International Conference on Electronic communication and Artificial Intelligenc…

2024年抖店什么类目赚钱?这八个类目最赚钱,想开店的快来瞅瞅!

哈喽~我是电商月月 做抖音小店的商家都知道&#xff0c;选品是非常重要的 那什么样的商品类型赚钱&#xff0c;哪些商品又适合新手操作呢? 今天我就给大家推荐几个热销类目&#xff0c;特别是最后两个&#xff0c;下半年说不定会小爆一把哦 一&#xff0e;日用百货 这个类…

MySQl删除数据后释放空间

在MySQL中&#xff0c;当你删除表中的数据时&#xff0c;空间通常不会自动释放回操作系统。这是因为MySQL为了性能而保留了这些空间。如果你确实需要释放这些空间&#xff0c;可以使用OPTIMIZE TABLE命令&#xff0c;它会重建表并释放未使用的空间。 sqlOPTIMIZE TABLE your_t…

为什么3d重制变换模型会变形?---模大狮模型网

3D建模和渲染过程中&#xff0c;设计师经常会遇到一个让人头疼的问题&#xff0c;那就是模型在进行重制变换后出现的意外变形。这种变形不仅影响了模型的外观和质量&#xff0c;也给设计工作带来了额外的麻烦。本文将深入探讨3D模型进行重制变换后出现变形的原因&#xff0c;帮…

Pytorch基础:torch.cuda.set_device函数

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html?spm1001.2014.3001.5482 torch.cuda.set_device函数用于设置当前使用的cuda设备&#xff0c;在当拥有多个可用的GPU且能被pytorch识别的cuda设备情况下&#xff08;环境变量CUDA_VISIBLE_…

【软考高项】四十六、项目管理科学计算之运筹学

1、线性规划问题 解题思路&#xff1a; 先把文字转化成图表 最快方式应该是把第一题的4个答案直接代入计算&#xff0c;很快得知X2时利润最大。 A0时&#xff0c;利润5*630 A2时&#xff0c;利润2*25*634 A4时&#xff0c;利润4*23*523 A6时&#xff0c;利润4*2(因为甲的…

【STM32HAL库】DAC输出0-3.3v

一、简要介绍一下DAC DAC也有分辨率&#xff0c;转换时间&#xff0c;精度等 分辨率常见为8或12位的 转换时间F1&#xff0c;F4,F7都是3us左右&#xff0c;而H7系列是1.7us 1.DAC框图 2.数据格式&#xff08;对齐方式&#xff09; 3.触发源 4.可以发送DMA请求 注意&#xff…

train_gpt2.c

llm.c/train_gpt2.c at master karpathy/llm.c (github.com) 源码 /* This file trains the GPT-2 model. This version is the clean, minimal, reference. As such: - it runs on CPU. - it does not make the code too complex; it is readable. - it does not use any p…

代码随想录第五十一天|最长递增子序列、最长连续递增序列、最长重复子数组

题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09;

基于STM32H750的DCMI接口OV5640摄像头条码识别

好久没写文章了&#xff0c;闭上眼睛&#xff0c;算了一下&#xff0c;大概有十年了&#xff0c;近来接到一个项目&#xff0c;需要做条码识别&#xff0c;客户要求用MCU做&#xff0c;理由成本低、价格可控。 于是乎&#xff0c;打开某宝软件&#xff0c;搜索后发现STM32H7/ST…

Pygame简单入门教程(绘制Rect、控制移动、碰撞检测、Github项目源代码)

Pygame简明教程 引言&#xff1a;本教程中的源码已上传个人Github: GItHub链接 视频教程推荐&#xff1a;YouTube教程–有点过于简单了 官方文档推荐&#xff1a;虽然写的一般&#xff0c;但还是推荐&#xff01; Navigator~ Pygame简明教程安装pygame一、代码框架二、案件输入…

YOLOv9-20240507周更说明|更新MobileNetv4等多种轻量化主干

专栏地址&#xff1a;目前售价售价69.9&#xff0c;改进点70 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 本周已更新说明&#xff1a; ### ⭐⭐更新时间&#xff1a;2024/5/12⭐⭐ 1. YOLOv9…

android studio apt代码编写实战

之所以试一下apt代码的编写&#xff0c;是因为发现几年前写的工程&#xff0c;在新的android studio中debug apt代码时&#xff0c;一直连不上debug环境&#xff0c;提示报错 Unable to open debugger port (localhost:5005): java.net.ConnectException "Connection refu…

C++之Eigen库基本使用(下)

1、常见变换 Eigen::Matrix3d //旋转矩阵&#xff08;3*3&#xff09; Eigen::AngleAxisd //旋转向量&#xff08;3*1&#xff09; Eigen::Vector3d //欧拉角&#xff08;3*1&#xff09; Eigen::Quaterniond //四元数&#xff08;4*1&#xff09; Eigen::Isom…

Java中的maven的安装和配置

maven的作用 依赖管理 方便快捷的管理项目依赖的资源&#xff0c;避免版本冲突问题 统一项目管理 提供标准&#xff0c;统一的项目结构 项目构建 标准跨平台&#xff08;Linux、windows、MacOS&#xff09;的自动化项目构建方式 maven的安装和配置 在maven官网下载maven Ma…