指针还是学不会?跟着小代老师学,进入深入理解指针(4)

指针还是学不会?跟着小代老师学,进入深入理解指针(4)

  • 1回调函数
  • 2qsort使用举例
    • 2.1使用qsort函数排序整行数据
    • 2.2使用qsort排序结构体数据
  • 3qsort函数的模拟实现

1回调函数

回调函数就是一个通过函数指针调用的函数
如果你把函数的指针(地址)作为一个参数传递给另外一个函数,当这个指针被用来调用其所指向的函数,被调用的函数就被称为回调函数。回调函数不是有函数的实现方直接调用的,而是在特定的事件或者条件发生时候由另一方调用,用来对该事件或者条件进行相应。
深入理解指针(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 = 0;int y = 0;int input = 0;int ret = 0;do{meun();printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("请输入两个数:");scanf("%d %d",& x,& y);ret=add(x, y);printf("%d", ret);break;case 2:printf("请输入两个数:");scanf("%d %d", &x,& y);ret = sub(x, y);printf("%d", ret);break;case 3:printf("请输入两个数:");scanf("%d %d", &x,& y);ret = mul(x, y);printf("%d", ret);break;case 4:printf("请输入两个数:");scanf("%d %d",& x,& y);ret = div(x, y);printf("%d", ret);break;case 0:printf("退出计算器"); break;default: printf("输入错误,请重新输入");break;}} while (input);
}
使用回调后
#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 cual (int(*pf)(int, int))
{int x = 0;int y = 0;printf("请输入两个数:");scanf("%d %d", &x, &y);int ret = pf(x, y);printf("%d", ret);
}
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 input = 0;do{meun();printf("请选择:");scanf("%d", &input);switch (input){case 1:cual(add);break;case 2:cual(sub);break;case 3:cual(mul);break;case 4:cual(div);break;case 0:printf("退出计算器"); break;default: printf("输入错误,请重新输入");break;}} while (input);

2qsort使用举例

让我们先了解下qsort在这里插入图片描述
在这里插入图片描述

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


#include<stdio.h>
int cmp(const void* p1, const void*p2)
{return(*(int *)p1 - *(int*)p2);
}
int main()
{int arr[10] = { 3,4,7,2,5,4,3,9,2,8 };int num = sizeof(arr) / sizeof(arr[0]);qsort(arr, num, sizeof(arr[0]), cmp);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

这边需要注意几个点,首先是qsort四个参数,最后一个参数是函数指针,指针也是地址,函数名本身就是一种地址。然后qsort默认是升序排序。

2.2使用qsort排序结构体数据

#include<stdio.h>
struct stu
{char name[20];int age;
};int cmp(const void* p1, const void*p2)
{return ((struct stu*)p1)->age - ((struct stu*)p2)->age;
}int main()
{struct stu arr[3] = { {"wang",192},{"zhang",16},{"li",18} };int num = sizeof(arr) / sizeof(arr[0]);qsort(arr, num, sizeof(arr[0]), cmp);for (int i = 0; i <3 ; i++){printf("%s,%d", arr[i].name,arr[i].age);}return 0;
}

这里总结下我出现的程序问题:
1.当我把结构体放在mian函数当中当作局部变量,编译会出现错误,当把他变为全局变量错误消失
在这里插入图片描述
在这里插入图片描述
2.我们对比下面两张部分代码
在这里插入图片描述
在这里插入图片描述
我们发现结构体强转时候需要把强转和指针变量再用括号包装一下,给的解释是结构体变量是临时的所以要再用括号包装一下啊,否则用不了。
而向int就可以直接强转。
3.还可以这样访问结构体成员
在这里插入图片描述

3qsort函数的模拟实现

使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。
注意:这⾥第⼀次使⽤ void* 的指针,讲解 void* 的作⽤。

#include<stdio.h>int comp(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
void swap( int with,char* p1, char* p2)
{for (int i = 0; i < with; i++){char temp = *p1;*p1 = *p2;*p2 = temp;*p1++;*p2++;}
}
void my_qsort_bubble_sort(void* base, int num, int with, int (*p_com)(const void*p1, const void*p2))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (p_com( (char*) base + j * with , (char*)base + (j + 1) * with)>0){swap(with,(char*)base + j * with, (char*)base + (j + 1) * with);}}}
}
int main()
{int arr[10] = { 2,3,45,21,4,5,9,0,3,20 };int num = sizeof(arr) / sizeof(arr[0]);int with = sizeof(arr[0]);my_qsort_bubble_sort(arr, num, with, comp);for (int i = 0; i < num; i++){printf("%d ", arr[i]);}return 0;
}

这里总结一下:当时敲完代码运行时候发现没有交换,结果检查发现是swap函数有了问题忘记给p1++,p2++了,做题关键思想是用回调函数,然后数值之间哪些要用指针来实现。

在这里插入图片描述在这里插入图片描述
这个是用模拟qsort来实现结构体排序。

#include<stdio.h>
struct stu{char name[20];int age;};
int comp(const void* p1, const void* p2)
{return ((struct stu*)p1)->age - ((struct stu*)p2)->age;
}
void swap( int with,char* p1, char* p2)
{for (int i = 0; i < with; i++){char temp = *p1;*p1 = *p2;*p2 = temp;*p1++;*p2++;}
}
void my_qsort_bubble_sort(void* base, int num, int with, int (*p_com)(const void*p1, const void*p2))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (p_com( (char*) base + j * with , (char*)base + (j + 1) * with)>0){swap(with,(char*)base + j * with, (char*)base + (j + 1) * with);}}}
}
int main()
{struct stu  arr[] = { {"man",20},{"fyy",30},{"xyy",10} };int num = sizeof(arr) / sizeof(arr[0]);int with = sizeof(arr[0]);my_qsort_bubble_sort(arr, num, with, comp);for (int i = 0; i < num; i++){printf("%s %d ", arr[i].name,arr[i].age);printf("\n");}return 0;
}

总结一下:
当时写好结构体时候,怎么找结构体成员都找不到,结果发现自己强转错误了。这里要注意下,我们强转时候一定要明白我们比较的类型是什么。
在这里插入图片描述

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

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

相关文章

小球的种类(ball)

小球的种类 题目描述 小红有 n n n种不同颜色的小球&#xff0c;第 i i i种颜色的小球有 a i a_i ai​个&#xff0c;放在同一个盒子中。 小红每次任意取出 k k k个小球并丢弃&#xff0c;直到盒子中剩余的球数小于 k k k个为止。 小红希望最终盒子里的小球颜色种类尽可能少…

荧光标记Avidin与特定生物分子的靶向结合-星戈瑞

亲和素Avidin是一种具有生物学特性的蛋白质&#xff0c;能够与生物素&#xff08;biotin&#xff09;进行高亲和力结合。通过荧光标记技术&#xff0c;我们可以将荧光基团与Avidin结合&#xff0c;形成荧光标记Avidin&#xff0c;从而实现对特定生物分子的靶向结合和可视化。 …

LeetCode-239.滑动窗口最大值

给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums [1,3,-1,-3,5,3,6,7], k 3 输…

【无标题】2024.6.6

2024.6.6 【一天高考&#xff01;&#xff01;&#xff01; “夏天周而复始、该相逢的人会再相逢”】 Thursday 五月初一 <theme oi-“DP”> 来学习一下DP的优化 其实考试时我应该很难用到优化的 P2569 [SCOI2010] 股票交易 DP柿子比较好推&#xff0c; T&#xff0…

I2C通信外设

I2C外设介绍 主机&#xff0c;就是拥有主动控制总线的权利。从机&#xff0c;只能在从机允许的情况下&#xff0c;才能控制总线。 多主机模型可分为固定多主机和可变多主机。固定多主机就是总线上&#xff0c;有2个或2个以上固定的主机&#xff0c;上面固定为主机&#xff0c;下…

【Unity | Editor强化工具】资产快速访问工具

经常在Project窗口中翻找资产相对麻烦&#xff0c;Unity自带的Favorite功能又和Project窗口强绑定&#xff0c;且只能在双列视图下使用&#xff0c;故制作了一个可以在独立窗口中列举常用资产的小工具&#xff1a; Unity Asset Quick Access 。 CSDN弄了个Github加速计划&…

在敏捷项目中如何使用WBS?

工作分解结构 (WBS) 是管理规划、监控和控制项目或计划范围的关键要素&#xff0c;在项目管理的许多不同分支中都有应用。它的主要目的是将复杂的项目分解成更易于管理的小块&#xff0c;通常以简单的流程图形式呈现。 WBS 通常与瀑布法等传统项目管理方法相关联&#xff0c;在…

教你申请永久免费的 us.kg 域名 支持接入 Cloudflare

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 之前的永久免费域名 eu.org 已经很久没有审批新的域名了&#xff0c;今天给大家推荐的 us.kg 不需要审批&#xff0c;注册账号申请域名后直接可以使用&#xff0c;并且它也可以像 eu.org 一样接入 Cloudfl…

2024中国机器人开发大会

具身智能 『 具有身体的智能 』 忘了是谁 小脑大模型&#xff1a;运动&#xff1b;大脑大模型&#xff1a;认知&#xff1b; 机器人操作系统 | 黄晓庆 云端&#xff0c;机器人的大脑&#xff0c;每个人的数字化&#xff0c;人类的第三台计算机&#xff1b;每个人生产力的提…

联合(union)和枚举(enum)学习(c语言)

前言 Hello,亲爱的小伙伴们&#xff0c;好久不见&#xff0c;今天我们继续来学习新的内容-----联合和枚举 如果喜欢作者菌的文章的话&#xff0c;就不要吝啬手中的三连呀&#xff0c;万分感谢&#xff01;&#xff01; 联合&#xff08;共用体&#xff09;&#xff08;union&…

【计算机网络】计算机网络的组成与功能

计算机网络的组成与功能 导读一、计算机网络的组成1.1 从组成方式上1.1.1 硬件1.1.2 软件1.1.3 协议 1.2 从工作方式上1.3 从功能组成上 二、计算机网络的功能2.1 数据通信2.2 资源共享2.3 分布式处理2.4 提高可靠性2.5 负载均衡2.6 其它 结语 导读 大家好&#xff0c;很高兴又…

【python基础篇】 5. python 异常、文件与流

1 异常 错误&#xff1a;语法错误&#xff08;一般IDE能够发现&#xff09;&#xff0c;逻辑错误&#xff08;很难发现&#xff0c;提示起来比较麻烦&#xff09; 异常&#xff1a;当python检测到一个错误时&#xff0c;解释器无法继续执行下去&#xff0c;于是抛出相应的信息…

Web3开发框架分析

Web3开发框架旨在简化区块链和去中心化应用&#xff08;DApp&#xff09;的开发过程&#xff0c;为开发者提供必要的工具和库。以下是一些主要的Web3开发框架。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.Truffle Suite Truffl…

$MPC 登录MEXC,加速Partisia Blockchain 生态市场进程

Partisia Blockchain是一个以MPC技术方案为基础&#xff0c;具备可审计特性的隐私Layer1生态&#xff0c;与此同时&#xff0c;该链通过系列创新的系统架构&#xff0c;能够兼顾高迸发、安全、可拓展性以及可互操作特性。基于系列技术特性&#xff0c;Partisia Blockchain正在构…

OrangePi KunPengPro | linux系统下挂载U盘

OrangePi KunPengPro | linux系统下挂载U盘 时间&#xff1a;2024年6月6日21:32:53 文章目录 OrangePi KunPengPro | linux系统下挂载U盘1.参考2.操作fdisk -l 列出系统上所有磁盘的分区表信息将 /dev/sda1 分区挂载到 /mnt/udisk/ 目录显示文件系统的磁盘空间使用情况卸载文件…

RAG检索增强生成(1)-大语言模型的外挂数据库

Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks Lewis P, Perez E, Piktus A, et al. Retrieval-augmented generation for knowledge-intensive nlp tasks[J]. Advances in Neural Information Processing Systems, 2020, 33: 9459-9474. RAG结合了信息检…

python中B.py调用A.py中所有方法,该怎么导入呢

函数调用 python中B.py调用A.py中所有方法&#xff0c;该怎么导入呢1. 确保A.py和B.py在同一目录2. 在A.py中定义一些方法3. 在B.py中导入A.py并调用其方法4. 运行B.py详细解释额外提示 2 采用from A.py import *是否可行1. 确保A.py和B.py在同一目录2. 在A.py中定义一些方法3.…

Java数据结构与算法(最长回文子串动态规划)

前言 动态规划主要用于解决具有重叠子问题和最优子结构性质的问题。它通过将问题分解为子问题来解决复杂问题&#xff0c;每个子问题仅解决一次&#xff0c;并将其结果存储&#xff0c;以供后续使用&#xff0c;从而避免了重复计算。 动态规划的基本思想 分解问题&#xff1…

C++入门 ros服务通信

一、 开发环境 ubuntu20.04 ros版本noetic 参考视频 https://www.bilibili.com/video/BV1Ci4y1L7ZZ/?p52&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source4cd1b6f268e2a29a11bea5d2568836ee 二、 编写srv文件 在功能包下面创建srv文件夹…

【SpringBoot + Vue 尚庭公寓实战】项目初始化准备(二)

尚庭公寓SpringBoot Vue 项目实战】项目初始化准备&#xff08;二&#xff09; 文章目录 尚庭公寓SpringBoot Vue 项目实战】项目初始化准备&#xff08;二&#xff09;1、导入数据库2、创建工程3、项目初始配置3.1、SpringBoot依赖配置3.2、创建application.yml文件3.3、创建…