程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<7>

在这里插入图片描述

大家好啊,我是小象٩(๑òωó๑)۶
我的博客:Xiao Xiangζั͡ޓއއ

很高兴见到大家,希望能够和大家一起交流学习,共同进步
在这里插入图片描述

今天我们一起来学习转移表,回调函数,qsort…

目录

  • 一、转移表
    • 1.1 定义与原理
    • 1.3 优点
  • 二、回调函数是什么?
    • 1.1 原理
    • 1.2 使用方法
    • 1.3 优点
  • 三、qsort 使用举例
    • 3.1 使用qsort函数排序整型数据
    • 3.2 使用qsort排序结构数据
  • 四、结尾

一、转移表

在 C 语言中,转移表(Jump Table)是一种用于实现多路分支选择的技术,也被称为跳转表或分支表。

1.1 定义与原理

转移表本质上是一个函数指针数组,数组中的每个元素都是一个指向函数的指针。它的原理是通过计算索引值来选择调用数组中的某个函数指针,从而实现根据不同条件跳转到不同代码段的功能,类似于根据索引查找表中的内容并执行相应操作。

1.3 优点

代码清晰简洁:
相比于使用大量的if-else语句或switch语句嵌套,转移表能使代码结构更加清晰,逻辑更加直观。尤其是在处理多个分支情况时,代码的可读性更高。
高效性:
在执行多路分支选择时,转移表的查找和跳转操作通常比复杂的if-else或switch判断更快。因为它主要通过数组索引直接定位到目标函数,而不需要逐个进行条件判断。
可扩展性:
当需要添加新的分支或功能时,只需在转移表中添加相应的函数指针,并实现对应的函数逻辑即可,对原有代码的改动较小,易于维护和扩展。

举例:计算器的⼀般实现:

#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(" 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;
}

使⽤函数指针数组的实现:

#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;int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表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);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");}} while (input);return 0;
}

二、回调函数是什么?

回调函数是一个作为参数传递给另一个函数的函数,而接收回调函数作为参数的函数会在合适的时候调用这个传递进来的函数。简单来说,就是 A 函数将 B 函数作为参数传递给 C 函数,C 函数在某个时刻调用 B 函数,此时 B 函数就是回调函数。

1.1 原理

回调函数的核心原理基于函数指针。在 C 语言中,函数名本质上代表该函数的入口地址,而函数指针则可以存储这个地址。通过将函数指针作为参数传递给另一个函数,接收该参数的函数就可以在需要的时候通过这个指针调用对应的函数。

1.2 使用方法

以下是使用回调函数的基本步骤:
定义回调函数:首先要定义一个符合特定参数和返回值要求的函数,这个函数将作为回调函数使用。
定义接收回调函数作为参数的函数:该函数需要有一个函数指针类型的参数,用于接收回调函数的地址。
调用接收回调函数的函数:在调用时,将回调函数的名称作为参数传递给接收回调函数的函数。

1.3 优点

灵活性:通过回调函数,可以在不修改接收回调函数的函数的源代码的情况下,改变其行为。只需要传递不同的回调函数,就可以实现不同的功能。
代码复用:可以将一些通用的逻辑封装在接收回调函数的函数中,而将具体的处理逻辑放在回调函数中。这样,不同的回调函数可以复用接收回调函数的函数的代码。
异步编程:在异步编程中,回调函数非常有用。当某个操作完成时,可以通过回调函数通知调用者进行后续处理。

//使⽤回调函数改造前
#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;

三、qsort 使用举例

qsort 是 C 标准库中用于对数组进行快速排序的函数,它基于快速排序算法实现,能对任意类型的数组进行排序。

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

#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.2 使用qsort排序结构数据


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;
}

注意事项
比较函数的实现:比较函数的实现要正确,确保能准确反映元素之间的大小关系。不同的比较函数实现可以实现升序、降序或其他自定义的排序规则。
类型转换:在比较函数中,由于 qsort 函数的通用性,传入的参数是 const void *
类型,需要将其转换为实际的数据类型才能进行比较操作。 稳定性:qsort
是不稳定的排序算法,即相等元素的相对顺序在排序后可能会改变。如果需要稳定的排序算法,可以考虑使用其他排序函数或自行实现稳定排序。
性能:qsort 平均时间复杂度为 (O(n log n)),但在最坏情况下时间复杂度为
(O(n^2))。不过在大多数实际应用场景中,它的性能表现良好。

四、结尾

这一课的内容就到这里了,下节课继续学习指针的其他一些知识
如果内容有什么问题的话欢迎指正,有什么问题也可以问我!
在这里插入图片描述

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

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

相关文章

漏洞分析 Spring Framework路径遍历漏洞(CVE-2024-38816)

漏洞概述 VMware Spring Framework是美国威睿&#xff08;VMware&#xff09;公司的一套开源的Java、JavaEE应用程序框架。该框架可帮助开发人员构建高质量的应用。 近期&#xff0c;监测到Spring Framework在特定条件下&#xff0c;存在目录遍历漏洞&#xff08;网宿评分&am…

笔记:理解借贷相等的公式

强烈推荐非会计人士&#xff0c;快速了解会计看这个系列的视频&#xff0c;其中比较烧脑的“借贷相等”公式&#xff0c;这个视频讲解的不错&#xff1a; 4.小白财务入门-借贷记账法_哔哩哔哩_bilibili 比如这里&#xff0c;钱在银行卡重&#xff0c;所以银行存款就是借方…

【Spring】什么是Spring?

什么是Spring&#xff1f; Spring是一个开源的轻量级框架&#xff0c;是为了简化企业级开发而设计的。我们通常讲的Spring一般指的是Spring Framework。Spring的核心是控制反转(IoC-Inversion of Control)和面向切面编程(AOP-Aspect-Oriented Programming)。这些功能使得开发者…

学习笔记:机器学习中的数学原理(一)

1. 集合 集合分为有限集和无限集&#xff1b; 对于有限集&#xff0c;两集合元素数相等即为等势&#xff1b; 对于无限集&#xff0c;两集合元素存在一一映射关系即为等势&#xff1b; 无限集根据是否与正整数集等势分为可数集和不可数集。 2. sigmoid函数&#xff08;也叫…

【信息系统项目管理师-案例真题】2016下半年案例分析答案和详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一【问题1】4 分【问题2】12 分【问题3】3 分【问题4】6 分试题二【问题1】3 分【问题2】4 分【问题3】8 分【问题4】5 分【问题5】5 分试题三【问题1】4 分【问题2】8 分【问题3】5 分【问题4】8 分试题一…

基于javaweb的SpringBoothis智能医院管理系统(源码+文档+部署讲解)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 运行环境开发工具适用功能说明一、项目运行 环境配置&#xff1a; 运行环境 Java≥8、MySQL≥5.7、Node.js≥14 开发工具 后端&…

JS实现灯光闪烁效果

在 JS中&#xff0c;我们可以实现灯光闪烁效果&#xff0c;这里主要用 setInterval 和 clearInterval 两个重要方法。 效果图 源代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>灯闪烁效果<…

7.PPT:“中国梦”学习实践活动【20】

目录 NO1234​ NO5678​ NO9\10\11 NO1234 考生文件夹下创建一个名为“PPT.pptx”的新演示文稿Word素材文档的文字&#xff1a;复制/挪动→“PPT.pptx”的新演示文稿&#xff08;蓝色、黑色、红色&#xff09; 视图→幻灯片母版→重命名&#xff1a;“中国梦母版1”→背景样…

学习笔记十九:K8S生成pod过程

K8S生成pod过程 流程图具体生成过程用户提交 Pod 定义API Server 处理请求调度器分配节点&#xff08;Scheduling&#xff09;目标节点上的 Pod 创建网络配置状态上报与监控控制器管理&#xff08;Controller Manager&#xff09;就绪与服务发现 关键错误场景高级特性 流程图 具…

封装descriptions组件,描述,灵活

效果 1、组件1&#xff0c;dade-descriptions.vue <template><table><tbody><slot></slot></tbody> </table> </template><script> </script><style scoped>table {width: 100%;border-collapse: coll…

21.2.6 字体和边框

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 通过设置Rang.Font对象的几个成员就可以修改字体&#xff0c;设置Range.Borders就可以修改边框样式。 【例 21.6】【项目&#xff…

360手机刷机 360手机解Bootloader 360手机ROOT

360手机刷机 360手机解Bootloader 360手机ROOT 问&#xff1a;360手机已停产&#xff0c;现在和以后&#xff0c;能刷机吗&#xff1f; 答&#xff1a;360手机&#xff0c;是肯定能刷机的 360手机资源下载网站 360手机-360手机刷机RootTwrp 360os.top 360rom.github.io 一、…

链表专题-02

链表专题 /*** 链表的节点* param <E>*/ public class ListNode<E> {public E element;public ListNode<E> next;public ListNode() {}public ListNode(E element) {this.element element;}public ListNode(E element, ListNode<E> next) {this.eleme…

外部中断实验 #STM32F407

外部中断实验 此实验将外部中断配置为按键输入&#xff0c;通过按键输入触发外部中断&#xff0c;在外部中断里面实施相应的处理&#xff0c;具体功能&#xff1a; 按下KEY0&#xff0c;翻转LED0状态按下KEY1&#xff0c;翻转LED1状态按下KEY2&#xff0c;同时翻转LED0和LED1…

机器学习8-卷积和卷积核1

机器学习8-卷积和卷积核1 卷积与图像去噪卷积的定义与性质定义性质卷积的原理卷积步骤卷积的示例与应用卷积的优缺点优点缺点 总结 高斯卷积核卷积核尺寸的设置依据任务类型考虑数据特性实验与调优 高斯函数标准差的设置依据平滑需求结合卷积核尺寸实际应用场景 总结 图像噪声与…

SVN 提交与原有文件类型不一样的文件时的操作

SVN 提交与原有文件类型不一样的文件时的操作 背景 SVN 服务器上原本的文件是软链接类型的&#xff0c;但是我将它改成普通文件再上传。出现了以下提示&#xff1a; 解决过程 本来想着通过 svn rm 和 svn add 来解决&#xff0c;但是行不通。 最终解决方案 svn rm --keep-…

阿里云专有云网络架构学习

阿里云专有云网络架构 叶脊&#xff08;spine-leaf&#xff09;网络和传统三层网络拓扑对比 阿里云网络架构V3拓扑角色介绍推荐设备设备组网举例带外管理网络带外网和带内网对比设备介绍 安全网络设备介绍 参考 后续更新流量分析叶脊&#xff08;spine-leaf&#xff09;网络和传…

Deepseek本地部署指南:在linux服务器部署,在mac远程web-ui访问

1. 在Linux服务器上部署DeepSeek模型 要在 Linux 上通过 Ollama 安装和使用模型&#xff0c;您可以按照以下步骤进行操作&#xff1a; 步骤 1&#xff1a;安装 Ollama 安装 Ollama&#xff1a; 使用以下命令安装 Ollama&#xff1a; curl -sSfL https://ollama.com/download.…

3D数字化营销:重塑家居电商新生态

随着电商的蓬勃发展&#xff0c;网上订购家具已成为众多消费者的首选。然而&#xff0c;线上选购家具的诸多挑战&#xff0c;如风格不匹配、尺寸不合适、定制效果不如预期以及退换货不便等&#xff0c;一直困扰着消费者。为解决这些问题&#xff0c;家居行业急需一种全新的展示…

重塑“景区+商业”模式,打造特色文旅新体验

重塑“景区商业”模式&#xff0c;打造特色文旅新体验 近年来&#xff0c;旅游业蓬勃发展&#xff0c;旅游热潮不断升温&#xff0c;游客消费观念也随之升级。为顺应这一趋势&#xff0c;各大景区纷纷探索打造特色文旅项目&#xff0c;以期吸引更多游客。然而&#xff0c;“景…