浅学指针(4)函数指针数组和qsort的使用

news2025/1/10 21:48:15

系列文章目录

文章目录

  • 系列文章目录
  • 前言
  • 1.函数指针数组的⽤途
    • 作用:可以让代码更简洁,逻辑更清晰
  • 2. 回调函数
    • 回调函数就是⼀个通过函数指针调⽤的函数
  • 3 . qsort函数
    • qsort函数可以排序所有数据类型
    • 解释如图:![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a3eca975d2f1467db785660acf7e0209.png) 比较函数是用函数指针接收,内部实现后面我还会讲
    • 3. 1使⽤qsort排序结构体数据
  • 5 ..qsort函数的模拟实现
    • 补充:qsort可以排所有的数据类型,下面写的代码是qsort内部实现


前言

掌握函数指针数组的使用,qsort函数的实现。

1.函数指针数组的⽤途

作用:可以让代码更简洁,逻辑更清晰

计算机的实现:
简单的加减法运算
代码1

#include <stdio.h>
int add(int a, int b)//加法
{
 	return a + b;
}
int sub(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(" 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;
 	default:
 		printf("选择错误\n");
 		break;
 	}
 } while (input);
 return 0;
}

在这里插入图片描述
这个时候就可以用函数指针数组了,
改造:
代码2

#include <stdio.h>
int add(int a, int b)
{
 	return a + b;
}
int sub(int a, int b)
{
 	return a - b;
}
void calc(int(*pf)(int, int))
{
 	int ret = 0;
 	int x, y;
 	printf("输⼊操作数:");
 	scanf("%d %d", &x, &y);
 	ret = pf(x, y);
 	printf("ret = %d\n", ret);
}
int main()
{
 	int x, y;
 	int input = 1;
 	int ret = 0;
 	int(*p[3])(int x, int y) = { 0, add, sub }; //转移表
 do
 {
  	printf("*************************\n");
 	printf(" 1:add 			   2:sub \n");
 	printf(" 0:exit 				 \n");
 	printf("*************************\n");
 	printf("请选择:");
 	scanf("%d", &input);
	if ((input <= 4 && input >= 1)){
 		printf( "输⼊操作数:" );
 		scanf( "%d %d", &x, &y);
 		ret = (*p[input])(x, y);
 		printf( "ret = %d\n", ret);
 	}
 	else if(input == 0)
 	{
 		printf("退出计算器\n");
 	}
 	else
 	{
 		printf( "输⼊有误\n" ); 
 	}
  	return 0;
}

看这样子是不是很简洁,那么是怎么调用的呢?

int(*p[3])(int x, int y) = { 0, add, sub };

如图:
在这里插入图片描述

2. 回调函数

回调函数就是⼀个通过函数指针调⽤的函数

如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。
回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。上面代码1中我们写的计算机的实现的代码中,红⾊框中的代码是重复出现的,其中虽然执⾏计算的逻辑是区别的,但是输⼊输出操作是冗余的,有没有办法,简化⼀些呢?
因为红⾊框中的代码,只有调⽤函数的逻辑是有差异的,我们可以把调⽤的函数的地址以参数的形式传递过去,使⽤函数指针接收,函数指针指向什么函数就调⽤什么数,这⾥其实使⽤的就是回调函数的功能。

3 . qsort函数

qsort函数可以排序所有数据类型

传参必要参数:
在这里插入图片描述
那她是怎么实现的呢?
代码3:

#include <stdio.h>
//qosrt函数的使⽤者得实现⼀个⽐较函数
int int_cmp(const void * p1, const void * p2)
{
 	return (*( int *)p1 - *(int *) p2);
}
int main()
{
 	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
 	int i = 0;
 
 	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), 	int_cmp);
 for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
 {
 		printf( "%d ", arr[i]);
 }
 		printf("\n");
 return 0;
}

解释如图:在这里插入图片描述
比较函数是用函数指针接收,内部实现后面我还会讲

3. 1使⽤qsort排序结构体数据

可以按名字,也可以按年龄
代码4:

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;
}
//strcmp - 是库函数,是专⻔⽤来⽐较两个字符串的⼤⼩的
//假设按照名字来⽐较
int cmp_stu_by_name(const void* e1, const void* e2)
{
 	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//按照年龄来排序
void test2()
{
 	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);
}
//按照名字来排序
void test3()
{
 	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_name);
}
int main()
{
 	test2();
 	test3();
 return 0;
}

其中代码解释,如图:
在这里插入图片描述

5 …qsort函数的模拟实现

使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。

补充:qsort可以排所有的数据类型,下面写的代码是qsort内部实现

注意:这⾥第⼀次使⽤ void* 的指针,讲解 void* 的作⽤。

#include<stdio.h>
int int_cmp(const void * p1, const void * p2)//比较函数跟qsort函数的比较函数一样
{
 	return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size)
{
 	int i = 0;
 	for (i = 0; i< size; i++)//因为不知道数据类型(void)所以两个元素选择一个一个字节交换
 	{
 		char tmp = *((char *)p1 + i);
 		*(( char *)p1 + i) = *((char *) p2 + i);
 		*(( char *)p2 + i) = tmp;
 	}
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
 	int i = 0;
 	int j = 0;
 for (i = 0; i< count - 1; i++)
  {
	for (j = 0; j<count-i-1; j++){//和冒泡相似
 		if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)//cmp函数返回值是int,判断>0,如果成立,执行语句
 		{
 			_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);//size是宽度,不知道
 		}
	}
  }
 }
int main()
{
 	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
 	int i = 0;
 	bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
 	for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)//打印
 	{
 		printf( "%d ", arr[i]);
 	}
 	printf("\n");
 return 0;
}

解析:在上面代码注释里,还有if语句代码的解释,如图:
在这里插入图片描述
好了,这就是今天所有的内容啦!宝子们都看到这里了,点一个赞,谢谢,下期再见.

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

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

相关文章

CAP概念和三种情况、Redis和分布式事务的权衡

借鉴&#xff1a;https://cloud.tencent.com/developer/article/1840206 https://www.cnblogs.com/huanghuanghui/p/9592016.html 一&#xff1a;CAP概念和三种情况 1.概念&#xff1a; C全称Consistency&#xff08;一致性&#xff09;&#xff1a;这个表示所有节点返回的数…

基于SpringBoot高校心理教育辅导设计与实现

摘 要 随着Internet技术的发展&#xff0c;心理教育辅导系统应运而生&#xff0c;心理教育辅导系统为用户提供了一个更为便利的心理测试咨询平台。所以&#xff0c;为了充分满足高校学生心理教育辅导的需求&#xff0c;特开发了本高校心理教育辅导系统。 本高校心理教育辅导系统…

喜报 | 通付盾WAAP解决方案入选国家工业信息安全发展研究中心“2023年数字化转型自主创新解决方案优选案例”

为提升自主创新产品质量和技术创新能力&#xff0c;助力重点行业自主可控基础设施建设&#xff0c;加速重点行业数字化转型工作进程&#xff0c;促进重点行业产业链数字化升级&#xff0c;推动重点行业数字化、网络化、智能化发展。国家工业信息安全发展研究中心联合中国交通建…

CentOS系统环境搭建(二十二)——Git进阶

centos系统环境搭建专栏&#x1f517;点击跳转 文章目录 Git进阶1.更新代码2.只拉取Git仓库的部分目录内容2.1初始化空白仓库2.2配置git仓库2.3开启稀疏检出属性2.4设置指定拉取的目录2.5 更新代码 Git进阶 1.更新代码 基于上一篇文章CentOS系统环境搭建&#xff08;二十一&…

[Android]AlertDialog对话框

1.介绍AlertDialog AlertDialog是Android中常用的对话框组件之一&#xff0c;用于在应用程序中显示一些提示信息、警告、确认信息或者提供用户进行选择的界面。AlertDialog通常用于与用户进行交互&#xff0c;例如要求用户确认某个操作、输入一些信息或者从一组选项中选择一个。…

从文字到使用,一文读懂Kafka服务

文章目录 1. 什么是Kafka&#xff1f; 2. Kafka有什么特点&#xff0c;优缺点是什么&#xff1f; 3. Kafka 与 Zookeeper 服务的关系&#xff1f; 4. Kafka 的常见命令有哪些&#xff1f;5. Kafka 和 Zookeeper 服务如何结合&#xff1f;6. Kafka 生产者和消费者的流程图&#…

四川枢震栩电商:抖店的商品标题怎么设置?

在抖店平台上&#xff0c;商品标题是吸引顾客点击和购买的重要因素之一。一个好的商品标题能够吸引顾客的注意&#xff0c;准确传达商品的特点和卖点。那么&#xff0c;如何设置抖店的商品标题呢&#xff1f; 一、抖店的商品标题怎么设置&#xff1f; 首先&#xff0c;简洁明了…

单片机实验(三)

前言 实验一&#xff1a;利用定时器T1的中断控制P1.7引脚输出音频信号&#xff0c;启动蜂鸣器发出一段熟悉的与众不同的具有10个音节的音乐音频。 实验二&#xff1a;使用定时器/计数器来实现一个LCD显示年、月、日、星期 、时、分、秒的电子表&#xff0c;要求时和分可以方便…

云服务器anaconda(py39)+pytorch1.12.0(cu113)

用xshell连接ip地址&#xff0c;端口号22&#xff0c;输入用户密码 查看当前版本 conda -V conda info --envs 如果不是需要的版本&#xff0c;使用 anaconda-clean --yes rm -rf anaconda3 删除文件夹 安装anaconda 2022 10 py3.9 wget https://repo.anaconda.com/archi…

kafka 集群 ZooKeeper 模式搭建

Apache Kafka是一个开源分布式事件流平台&#xff0c;被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用程序 Kafka 官网&#xff1a;Apache Kafka 关于ZooKeeper的弃用 根据 Kafka官网信息&#xff0c;随着Apache Kafka 3.5版本的发布&#xff0c;Zookeeper现…

看这里!精确的用户画像是如何一步步构建的?

1. 用户画像的定义 用户画像是指根据用户的个人信息、行为特征和偏好等数据来描绘和分析用户的一种方法。它是通过收集和分析用户的各种数据&#xff0c;以便更好地了解用户需求和行为模式&#xff0c;从而为企业提供个性化、精准化的产品和服务。 2. 构建用户画像的步骤 &…

If和else的紧缩版本(Python)

epsilon_max 3 epsilon 2 epsilon_increment 1 epsilon epsilon * (1 epsilon_increment) if epsilon < epsilon_max else epsilon_max print(epsilon)

读书笔记-《数据结构与算法》-摘要1[数据结构]

文章目录 [数据结构]1. String - 字符串2. Linked List - 链表2.1 链表的基本操作2.1.1 反转链表单向链表双向链表 2.1.2 删除链表中的某个节点2.1.3 链表指针的鲁棒性2.1.4 快慢指针 3. Binary Tree - 二叉树3.1 树的遍历3.2 Binary Search Tree - 二叉查找树 4. Queue - 队列…

训练 CNN 对 CIFAR-10 数据中的图像进行分类-keras实现

1. 加载 CIFAR-10 数据库 import keras from keras.datasets import cifar10# 加载预先处理的训练数据和测试数据 (x_train, y_train), (x_test, y_test) cifar10.load_data() 2. 可视化前 24 个训练图像 import numpy as np import matplotlib.pyplot as plt %matplotlib …

桶装水订水送水小程序具备以下主要功能

桶装水订水送水小程序具备以下主要功能&#xff1a; 对比传统的电话订水&#xff0c;订水小程序展现出显著的优势&#xff1a; 1. 便捷性&#xff1a;用户通过小程序就能轻松预订水桶&#xff0c;无需亲自出门&#xff0c;极大提升了生活的便捷度。 2. 即时性&#xff1a;送水…

element-ui表格滚动效果,el-table滚动条样式重置

项目首页需要展示一个表格滚动区域&#xff0c;特此来记录一下 HTML <div class"table-box" mouseenter"mouseenter" mouseleave"mouseleave"><el-table :data"tableList" border height"400px" v-loading"…

2023_Spark_实验二十四:Kafka集群环境搭建

Kafka集群环境搭建 一、环境说明 二、安装步骤 一、环境说明 目前的Kafka版本还是需要借助zookeeper来存储cluster、brokers、consumer等相关元信息&#xff0c;在当前版本即 在本案例中&#xff0c;我们采用了外部的zookeeper&#xff0c;即搭建了三节点的集群zookeeper环境…

Python Scrapy分布式爬虫

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在当今信息爆炸的时代&#xff0c;获取大规模数据对于许多应用至关重要。而分布式爬虫作为一种强大的工具&#xff0c;在处理大量数据采集和高效爬取方面展现了卓越的能力。 本文将深入探讨分布式爬虫的实际应用…

最新Graphviz python安装教程及使用

文章目录 Graphviz 安装python安装graphviz库 Graphviz 安装 Graphviz是一个独立的软件&#xff0c;在用python的pip下载之前&#xff0c;需要先下载软件。 网址&#xff1a;https://graphviz.org/download/ 找到合适的版本进行下载安装。记住自己的安装位置&#xff0c;完…

如何通过数据文化加速企业管理的转型升级?

#01 企业管理 更需要“转型升级” 中国企业管理在某种程度上来看&#xff0c;受到中国传统文化、社会价值观及现代化趋势等多方面影响的结果&#xff0c;比如说&#xff0c;中国传统文化强调长期思考和计划&#xff0c;这在企业管理中体现为对长期业务发展和可持续的关注。但…