C语言.指针(4)

指针(4)

  • 1.回调函数是什么?
  • 2.qsprt使用举例
    • 2.1使用qsort函数排序整型数据
    • 2.2使用qsort函数排序结构体数据
  • 3.qsort函数的模拟实现

1.回调函数是什么?

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

  1. 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数
  2. 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

在指针(3)中我们写的计算机的实现的代码中,有一部分代码是重复出现的,其中虽然执行计算的逻辑是区别的,但是输入输出操作是冗余的,有没有办法,简化⼀些呢?

因为在计算机的实现的代码中,只有调用函数的逻辑是有差异的,可以把调用的函数的地址以参数的形式传递过去,使用函数指针接收,函数指针指向什么函数就调用什么函数,这里其实使用的就是回调函数的功能。

//使用回调函数之前
#include<stdio.h>//实现加法
int Add(int x, int y)
{return x + y;
}
//实现减法
int Sub(int x, int y)
{return x - y;
}
//实现乘法
int Mul(int x, int y)
{return x * y;
}
//实现除法
int Div(int x, int y)
{return x / y;
}//菜单
void meun()
{printf("-------------------\n");printf("--- 1.Add 2.Sub ---\n");printf("--- 3.Mul 4.Div ---\n");printf("---    0.Exit   ---\n");printf("-------------------\n");
}int main()
{int x, y = 0;int input = 0;int ret = 0;do{meun();printf("请选择:>");scanf("%d", &input);switch (input){default:printf("选择错误,请重新选择\n");break;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;}} while (input);return 0;
}
//使用回调函数之后
#include<stdio.h>//实现加法
int Add(int x, int y)
{return x + y;
}
//实现减法
int Sub(int x, int y)
{return x - y;
}
//实现乘法
int Mul(int x, int y)
{return x * y;
}
//实现除法
int Div(int x, int y)
{return x / y;
}//菜单
void meun()
{printf("-------------------\n");printf("--- 1.Add 2.Sub ---\n");printf("--- 3.Mul 4.Div ---\n");printf("---    0.Exit   ---\n");printf("-------------------\n");
}//回调函数
void calc(int (*pf)(int, int))
{int x, y = 0;int ret = 0;printf("请输入两个数: ");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}int main()
{int input = 0;do{meun();printf("请选择:>");scanf("%d", &input);switch (input){default:printf("选择错误,请重新选择\n");break;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;}} while (input);return 0;
}

2.qsprt使用举例

2.1使用qsort函数排序整型数据

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

2.2使用qsort函数排序结构体数据

#include<stdio.h>
#include<string.h>struct Stu //学生
{char name[10];//名字int age;//年龄
};//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}//假如按照年龄来比较
void test1()
{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 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_name);
}int main()
{test1();test2();return 0;
}

3.qsort函数的模拟实现

使用回调函数,模拟实现qsort(采用冒泡的排序方式)

代码1:

//使用bubble_sort函数排序整型数据
#include<stdio.h>int int_cmp(const void* p1, const void* p2)
{return ((*(int*)p1) - (*(int*)p2));
}//交换
void Swap(void* buf1, void* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *((char*)buf1 + i);*((char*)buf1 + i) = *((char*)buf2 + i);*((char*)buf2 + i) = tmp;}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);//使用回调函数,模拟实现qsortbubble_sort(arr, sz, sizeof(arr[0]), int_cmp);//打印for (size_t i = 0; i < sz; i++){printf("%d ", arr[i]);//0 1 2 3 4 5 6 7 8 9}printf("\n");return 0;
}

代码2:

//使用bubble_sort函数排序结构体数据
#include<stdio.h>
#include<string.h>struct Stu //学生
{char name[10];//名字int age;//年龄
};//交换
void Swap(void* buf1, void* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *((char*)buf1 + i);*((char*)buf1 + i) = *((char*)buf2 + i);*((char*)buf2 + i) = tmp;}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}//假如按照年龄来比较
void test1()
{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);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}//假如按照名字来比较
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_name);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}int main()
{test1();test2();return 0;
}

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

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

相关文章

Java集合体系面试题

1. Java中有哪些主要的集合接口&#xff1f; 答案&#xff1a;Java中主要的集合接口有Collection、List、Set、Queue和Map。 2. 请解释List和Set之间的主要区别。 答案&#xff1a;List和Set的主要区别在于元素的顺序和唯一性。List是有序的集合&#xff0c;允许存储重复的元…

PHP安装swoole拓展

一&#xff1a;下载swoole拓展 PHP的swoole拓展下载地址&#xff1a;https://pecl.php.net/package/swoole wget http://pecl.php.net/get/swoole-4.2.12.tgz二&#xff1a;安装swoole拓展 1&#xff1a;解压swoole拓展包 tar xzvf swoole-4.2.12.tgz cd swoole-4.2.122&am…

pandas(day6 图表)

一. 计算效率 1. 测量代码运行时间 %%time %%timeit 单纯计算 代码块执行的时长 %%time _sum(np.arange(6)) CPU times: total: 0 ns Wall time: 1.66 ms用于多次运行代码块并计算平均执行时间 %%timeit _sum(np.arange(6))738 ns 10.7 ns per loop (mean std. dev. of 7…

java常用设计模式介绍及代码示例

设计模式是在软件设计中发现、研究和应用的一种有效方法。设计模式并不直接转化成代码&#xff0c;而是提供了解决某一问题的框架。下面介绍一些常用的设计模式以及对应的Java代码示例&#xff1a; 1. 单例模式&#xff1a;确保某一个类只有一个实例&#xff0c;同时提供一个访…

java流式计算Stream

java流式计算Stream 流(Stream)到底是什么呢? 是数据渠道&#xff0c;用于操作数据源&#xff08;集合、数组等&#xff09;所生成的元素序列。 “集合讲的是数据&#xff0c;流讲的是计算! ” 特点&#xff1a; Stream自己不会存储元素。 Stream不会改变源对象。相反&#x…

金三银四面试题(十六):MySQL面试都问什么(1)

在开发岗位面试中&#xff0c;MySQL基本是必考环节。所以接下来我们就进入MySQL八股文环节&#xff0c;看看都有哪些高频考题。 MySQL 中有哪些不同的表格&#xff1f; 在MySQL中&#xff0c;可以创建多种不同类型的表格&#xff0c;其中一些常见的类型包括&#xff1a; InnoD…

代码随想录第18天: 二叉树part05

力扣513 找树左下角的值 class Solution {public int findBottomLeftValue(TreeNode root) {Queue<TreeNode> que new LinkedList<>();que.offer(root);int res 0;while(!que.isEmpty()) {int size que.size();for(int i 0; i < size; i) {TreeNode tmp q…

Git(8)之分支间同步特定提交

Git(8)之分支间同步特定提交 Author&#xff1a;Once Day Date&#xff1a;2024年4月7日 漫漫长路有人对你微笑过嘛… 全系列文章可查看专栏: Git使用记录_Once_day的博客-CSDN博客 文章目录 Git(8)之分支间同步特定提交1. 分支间同步提交2. cherry-pick同步分支间的特定提交…

docker打包haproxy并代理web或mysql集群

1、需求&#xff1a; 使用haproxy代理两个服务&#xff08;web服务或者是mysql服务&#xff09; 2、编写Dockerfile 2.1、创建Dockerfile专用目录 mkdir /docker/images/haproxy -p && cd /docker/images/haproxy 2.2、下载软件包到Dockerfile专用目录 curl -O h…

性能优化-如何爽玩多线程来开发

前言 多线程大家肯定都不陌生&#xff0c;理论滚瓜烂熟&#xff0c;八股天花乱坠&#xff0c;但是大家有多少在代码中实践过呢&#xff1f;很多人在实际开发中可能就用用Async&#xff0c;new Thread()。线程池也很少有人会自己去建&#xff0c;默认的随便用用。在工作中大家对…

ThingsBoard通过MQTT发送属性数据

MQTT基础 客户端 MQTT连接 属性上传API 案例 MQTT基础 MQTT是一种轻量级的发布-订阅消息传递协议&#xff0c;它可能最适合各种物联网设备。 你可以在此处找到有关MQTT的更多信息&#xff0c;ThingsBoard服务器支持QoS级别0&#xff08;最多一次&#xff09;和QoS级别1&…

3D打印技术引领压铸模具制造新变革

随着工业4.0浪潮的席卷&#xff0c;3D打印技术以其独特优势&#xff0c;正逐渐成为新一轮工业革命中的璀璨明星。这一技术不仅为“中国制造”向“中国智造”的转型提供了强大动力&#xff0c;也为压铸模具这一铸造行业的重要分支带来了前所未有的变革。 压铸模具&#xff0c;作…

文心一言指令词宝典之咨询分析篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

深入浅出理解ArrayBuffer对象TypedArray和DataView视图

目录 举例理解 1. ArrayBuffer对象 2. TypedArray 3. DataView 总结 具体讲解 1. ArrayBuffer对象 2. TypedArray 3. DataView 注意事项 举例理解 先举个简单的例子理解ArrayBuffer对象TypedArray和DataView视图的概念和之间的关系 1. ArrayBuffer对象 想象一个场景…

2024.2.17力扣每日一题——N叉树的层序遍历

2024.2.17 题目来源我的题解方法一 广度优先搜索&#xff08;队列实现&#xff09; 题目来源 力扣每日一题&#xff1b;题序&#xff1a;429 我的题解 方法一 广度优先搜索&#xff08;队列实现&#xff09; 和二叉树的层序遍历相同&#xff0c;只是在添加子节点的细节有所不…

NAT网络地址转换原理解析

NAT&#xff08;Network Address Translation&#xff09;&#xff0c;即网络地址转换&#xff0c;是一种在1994年提出的地址转换技术。它的主要目的是在本地网络中使用私有地址&#xff0c;在连接互联网时转而使用全局IP地址。NAT实际上是为解决IPv4地址短缺而开发的技术。NAT…

MBTI测试背后的心理学原理:为什么它能揭示你的职业性格?(包含开源免费的API接口)

MBTI简介 迈尔斯-布里格斯类型指标&#xff08;Myers–Briggs Type Indicator&#xff0c;MBTI&#xff09;是由美国作家伊莎贝尔布里格斯迈尔斯和她的母亲凯瑟琳库克布里格斯共同制定的一种人格类型理论模型。 该指标以瑞士心理学家卡尔荣格划分的8种心理类型为基础&#xff…

[算法前沿]--022-使用 StarCoder 创建一个编程助手

文章目录 StarCoder调优测试StarCoder BigCode 开发的 StarCoder,这是一个在一万亿的 token、80 多种编程语言上训练过的 16B 参数量的模型。训练数据多来自 GitHub 上的 issues、使用 Git 提交的代码、Jupyter Notebook 等等 。得益于对企业友好的许可证、长度为 8192 的 to…

Mojo编程语言案例及介绍

Mojo是一种新兴的编程语言&#xff0c;它结合了现代编程范式与简洁易读的语法&#xff0c;为开发者提供了一个强大且高效的开发工具。以下将详细介绍Mojo编程语言的特性&#xff0c;并通过一个实际案例来展示Mojo的应用。 一、Mojo编程语言介绍 Mojo编程语言的设计理念是“简单…

以诚待人,用心做事,做到最好,追求更好

无数个日日夜夜&#xff0c;终于换来了这样一份努力的证明。 2023年&#xff0c;收获满满&#xff0c;前一阵子拿到了证书&#xff0c;忘记拍照了&#xff0c;今天抽空记录一下 收获&#xff01;又得到一份肯定&#xff0c;这份荣誉证书将伴随我一直为了进步而奋斗&#xff1a…