详解函数指针(●‘◡‘●)☞

news2025/1/11 7:09:51

本文紧接于http://t.csdn.cn/78wbF 这篇

一.函数指针数组\ ( >O< ) /

1.书写形式:由函数指针内部*+变量名==>*+变量名+[n];

2.使用:函数指针数组的用途:转移表

例如:模拟计算器:

#include<stdio.h>
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("*************************\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;
}

该代码有缺陷在于case里面会写很多个重复代码当使用函数指针数组则会减少该不足将主函数修改:

int main()
{
        int x, y;
        int input = 1;
        int ret = 0;
        int (*mid[5])(int*, int*) = {add,sub,mul,div};
        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:
            case 2:
            case 3:
            case 4:
                printf("输入操作数:");
                scanf("%d %d", &x, &y);
                ret = mid[input-1](x, y);
                ///ret = (*mid[input - 1])(x,y);这两种使用方法都可以。
                printf("ret = %d\n", ret);
                break;
            case 0:
                printf("退出程序\n");
                break;
            default:
                printf("选择错误\n");
                break;
            }
        } while (input);    
    return 0;
}

3.指向函数指针数组的指针

(1).书写形式:(以例说明)int (*(*p)[10])(int *,int *)=&arr;

拆分开来就是:最外层是函数指针==>内部的指针部分搞成数组指针===>再把数组指针进化成数组指针就行,一步一步来

二.回调函数。((o(^_ ^)o))

    • 书写形式:(以例说明)void(数据类型) part(函数名)(int (*pa)(int,int))里面是函数指针

    • 回调函数的意义(定义):

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个

函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数

的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进

行响应

3.回调函数的使用☞模拟qsort函数

(1).介绍qsort函数:用于比较1个数组的元素之间的大小

//void qsort(void* base, //待排序的数组的起始地址
//      size_t num,    //元素个数
//     size_t width,  //一个元素的大小
//      int (*cmp)(const void* e1, const void* e2)//两个元素的比较函数
//         );
#include<stdio.h>
#include<string.h>
struct Str { char a[10]; int b; };
struct Str s[3] = { {"zhangsan",20}, {"lisi", 50}, {"wangwu", 33} };
int  part(const void*a ,const void*b)//比较函数形式固定
{return strcmp(((struct Str*)a)->a, ((struct Str*)b)->a);}
int main()
{   int a = sizeof(s) / sizeof(s[0]);
    qsort(s,a,sizeof(s[0]),part);//比较字符串
    return 0;
}

void* 是指空数据类型,因为不知到要操作的是哪种数据类型。

qsort默认是升序排列的

注意自己写的函数开始是void*要转化成要求的类型(important)

(2).实现模拟qsort函数(注意点和解释放在代码注释中)

#include <stdio.h>
#include <string.h>//定义结构体
typedef struct student
{char name[20];int score;}student;
//自定义比较函数  使用strcmp函数比较字符串大小
int  compare_student(const void* r1, const void* r2)
{
    return strcmp((*((student**)r1))->name, (*((student**)r2))->name);
}
//交换函数,使用char*指针一个字节一个字节交换
void swap(char* r1, char* r2, size_t width)
{
    size_t  i = 0;
    for (i = 0; i < width; i++)
    {
        char temp = 0;
        temp = *r1;
        *r1 = *r2;
        *r2 = temp;
        r1++;
        r2++;
    }
}
//自定义qsort函数的实现
void My_bubble_qsort(void* base, size_t num, size_t width, int (*compare)(const void* r1, const void* r2))
{
    size_t i = 0;
    size_t j = 0;
    for (i = 0; i < num - 1; i++)
    {
        for (j = 0; j < num - 1 - i; j++)
        {
            if (compare((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}
int main()
{ student wangwu = { "wangwu",75 };
    student lisi = { "lisi",94 };
    student zhangsan = { "zhangsan",60 };
    student* arr_student[3] = { &wangwu,&lisi,&zhangsan };//定义结构体指针数组
    int i = 0;
    printf("排序前:\n");
    for (i = 0; i < 3; i++)
    {  printf("%s,%d\n", arr_student[i]->name, arr_student[i]->score); }
    My_bubble_qsort(arr_student, sizeof(arr_student) / sizeof(arr_student[0]), sizeof(arr_student[0]), compare_student);
    printf("\n排序后:\n");
    for (i = 0; i < 3; i++)
    {  printf("%s,%d\n", arr_student[i]->name, arr_student[i]->score); }
    return 0;
}

好了这就是今天的内容了,谢谢大家观看,希望大家多多指出不足。最后觉得小编写的还凑合的来个三连呀!

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

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

相关文章

用了这么久 IDEA,你还没用过 Live Templates 吗?

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」&#xff0c;专注于 Java技术 及周边生态。 Live Templates 是什么&#xff0c;听上去感觉挺玄乎的。有的同学用过之后觉得简直太好用了&#xff0c;不能说大大提高了开发效率吧&#xff0c;至少也是小小的提高一下…

Qt创建项目:手把手创建第一个Qt项目

上一节介绍了QtCreator编辑器的页面长什么样子&#xff0c;以及都有哪些功能区&#xff0c;每个功能区都是用来做什么的。这一节我就手把手带大家创建一个Qt项目。 创建项目 点击新建按钮 创建项目有两个入口&#xff0c;一个是在欢迎页面的projects中点击New(新建)按钮&…

未来,勒索软件会呈现何种发展态势?

尽管过去一年里&#xff0c;全世界大约花费了1500亿美元在网络安全领域上&#xff0c;却无法真正阻止黑客攻击。在过去一年里&#xff0c;针对医院、学校、政府的勒索软件越来越多&#xff1b;加密货币领域也有无休止的黑客盗窃事件&#xff1b;还有针对微软、英伟达、Rockstar…

CORS跨域通信

在上一集的坐牢文章中&#xff0c;我们介绍了非官方的很多中方案&#xff0c;其中不乏一些江湖秘术。今天的这个&#xff0c;绝对的正统&#xff0c;纯正的官方打造。我们赶紧来看看。 1.什么是CORS&#xff1f; CORS 是一个 W3C 标准&#xff0c;全称是“跨域资源共享”&…

Prometheus的使用

Prometheus 是一个开放性的监控解决方案&#xff0c;用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展。 在Prometheus的架构设计中&#xff0c;Prometheus Server 并不直接服务监控特定的目标&#xff0c;其主要任务负责数据的收集&#xff0c;存储并…

ArcGIS Engine基础(31)之使用仿射变换对矢量数据进行空间校正

在生产数据过程中&#xff0c;因每个工程项目都可能有自己的施工坐标系&#xff0c;难免会产生数据提供方与数据使用方采用的坐标系不一致&#xff0c;造成数据在不同坐标系下存在一定偏移、旋转、缩放等&#xff0c;为了让数据能够在新坐标系准确定位&#xff0c;需要进行空间…

kitti数据集理解及可视化

kitti数据集简介 kitti数据集是比较早出来的3D检测方面的数据集&#xff0c;相对来说数据结构简单&#xff0c;适合做单目检测的工作&#xff0c;目前也是业界和学术界常用的公开数据集。 自己最近也在做单目3D检测的工作&#xff0c;所以也分享一些理解&#xff0c;希望能给到…

微服务自动化管理【Docker跨主机集群之Flannel】

环境说明 CentOS7 etcd-v3.4.3-linux-amd64.tar.gz flannel-v0.11.0-linux-amd64.tar.gz 官方文档&#xff1a;https://github.com/coreos/flannel 下载地址&#xff1a;https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz 1.…

verilog学习笔记- 9)流水灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; LED&#xff0c;又名发光二极管。LED 灯工作电流很小&#xff08;有的仅零点几毫安即可发光&#xff09;&#xff0c;抗冲击和抗震性能好&…

工业互联网安全漏洞分析

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 研究背景 在政策与技术的双轮驱动下&#xff0c;工业控制系统正在越来越多地与企业内网和互联网相连接&#xff0c;并与新型服务模式相结合&#xff0c;逐步形成…

day01--Python学习笔记之安装及测试

目录 官网下载 1、Python自带简单的开发环境 2、Python的交互式命令行程序 3、官方技术文档 4、安装模块文档 1、Python自带简单的开发环境 在当前中编辑代码 在新文件中编辑代码 2、P…

springboot 使用tomcat详解

1.使用内嵌tomcat启动 创建tomcat对象设置端口设置Context设置servlet 和 路径 2.spring中单独注册servlet和地址的映射关系 Beanpublic ServletRegistrationBean getServletRegistrationBean() {ServletRegistrationBean bean new ServletRegistrationBean(apiServlet);bean…

免费GPU攻略

白嫖kaggle kaggle每周会送38个小时&#xff0c;16GB显存。 验证手机号 根据 kaggle问答可知&#xff0c;需要手机号短信验证&#xff0c;账号才能用GPU。国内的手机号都是可用的。操作如下&#xff1a; 点击右上角头像&#xff0c;点击Account。 到了个人详情页后&#xf…

基于JAVA springboot+mybatis智慧生活分享平台设计和实现

基于JAVA springbootmybatis智慧生活分享平台设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

【MySQL进阶】执行一条 sql 语句,期间会发生什么

【MySQL进阶】执行一条 sql 语句&#xff0c;期间会发生什么? 文章目录【MySQL进阶】执行一条 sql 语句&#xff0c;期间会发生什么?MySQL 执行流程是怎样的&#xff1f;第一步&#xff1a;连接器第二步&#xff1a;查询缓存第三步&#xff1a;解析 SQL解析器第四步&#xff…

Google Play Install Referrer API 和 Facebook App Ads Referral 集成

介绍&#xff1a;由于需要精准的获取投放广告的数据&#xff08;投放的平台&#xff0c;防止数据的丢失等&#xff09;。我们使用了Google Play Install Referrer API 和Facebook App Ads Referral结合采集数据&#xff0c;然后通过后台服务记录数据。最后服务器记录的数据与Fa…

openwrt tc(traffic contrl)配置及使用

在某些情况下&#xff0c;嵌入式设备需要用到弱网环境进行测试。网上针对tc的配置有很多&#xff0c;但是7688的没找到&#xff0c;所以做个记录&#xff0c;方便大家使用。netem配置 Kernel modules > Network Support > kmod-netemqos-scripts配置> Base system >…

甲氧基聚乙二醇-葡聚糖 mPEG-Dextran结构式;Dextran-PEG科研实验用

甲氧基聚乙二醇-葡聚糖 mPEG-Dextran 中文名称&#xff1a;甲氧基聚乙二醇-葡聚糖 英文名称&#xff1a;mPEG-Dextran 规格&#xff1a;500mg/1g/5g/10g 分散系数&#xff1a;小于等于1.05 分子量&#xff08;PEG&#xff09;&#xff1a;2000&#xff1b;3400&#xff1b…

Jmeter5.0之 dubbo插件安装

我记得之前 这个链接&#xff1a;https://github.com/ningyu1/jmeter-plugins-dubbo/tree/master/dist 能下载现成的dubbo插件&#xff0c;现在这个链接访问后提示404、网上搜索提供了最新的获取方式&#xff0c;1、访问链接&#xff1a;https://github.com/ningyu1/jmeter-plu…

ForkJoin

什么是ForkJoin ForkJoin在JDK1.7&#xff0c;并行执行任务&#xff01;提高效率&#xff0c;大数据量&#xff01; 大数据&#xff1a;Map Reduce&#xff08;把大任务拆分为小任务&#xff09; ForkJoin特点&#xff1a;工作窃取 这个里面维护的都是双端队列 当第一行的任务执…