C语言简单计算器实现(内含转移表、回调函数、主调函数介绍)

文章目录

  • 引入
    • 1.利用转移表改进
    • 2.什么是转移表
    • 3.利用回调函数改进
    • 4. 什么是回调函数

引入

函数指针数组的⽤途:转移表
举例:计算器的⼀般实现:
我们若用以前的代码实现:

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;
}void menu()
{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;int a = 0;int b = 0;int z = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Add(a, b);printf("%d\n", z);break;case 2:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Sub(a, b);printf("%d\n", z);break;case 3:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Mul(a, b);printf("%d\n", z);break;case 4:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Div(a, b);printf("%d\n", z);break;case 0:printf("退出程序!");break;default:printf("选择错误,请重新选择:\n");break;}} while (input);return 0;
}

运行一下:
在这里插入图片描述
运行无疑是没有什么问题的!

但是如果我们想要在此计算器中添加其他的计算,比如左移右移、取余等操作,我们不仅要写对应的函数,还要改下面的switch语句,略显麻烦,所以我们可以用函数指针数组来简化代码:

1.利用转移表改进

我们在启用计算器的时候必须输入一个值来确定进行怎样的运算,如果我们在输入值的同时就可以直接调用对应的函数不就可以省去switch语句吗?
这时候我们就要用函数指针数组,但确保输入的值与函数指针数组的下标匹配,所以我们加入一个0来进行调整:
在这里插入图片描述
我们用代码实现:

menu();
printf("请选择:");
scanf("%d", &input);
printf("请输入两个操作数:");
scanf("%d %d", &a, &b);
z = pfArr[input](a, b);
printf("%d\n", z);

加上if语句让代码更完全:

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;
}void menu()
{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;int a = 0;int b = 0;int z = 0;int (*pfArr[5])(int, int) = { 0, Add, Sub, Mul, Div };do{menu();printf("请选择:");scanf("%d", &input);if (input >= 1 && input <= 4){printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = pfArr[input](a, b);printf("%d\n", z);}else if (input == 0){printf("退出程序\n");}else{printf("输入错误,重新输入\n");}} while (input);return 0;
}

运行结果:
在这里插入图片描述

2.什么是转移表

这里的pfArr[5]就是一个转移表:

	int (*pfArr[5])(int, int) = { 0, Add, Sub, Mul, Div };

3.利用回调函数改进

除了用转移表来写,我们还可以有其他办法吗?
我们观察这个上面这段代码:

case 1:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Add(a, b);printf("%d\n", z);break;
case 2:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Sub(a, b);printf("%d\n", z);break;
case 3:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Mul(a, b);printf("%d\n", z);break;
case 4:printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = Div(a, b);printf("%d\n", z);break;

这串代码都在重复一样的操作,是否有些冗余:我们是不是可以将其包装成一个函数:

void calc(int (*pf)(int, int))
{int input = 0;int a = 0;int b = 0;int z = 0;printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = pf(a, b);printf("%d\n", z);
}

完整代码:

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;
}void menu()
{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 input = 0;int a = 0;int b = 0;int z = 0;printf("请输入两个操作数:");scanf("%d %d", &a, &b);z = pf(a, b);printf("%d\n", z);
}int main()
{int input = 0;int a = 0;int b = 0;int z = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出程序!");break;default:printf("选择错误,请重新选择:\n");break;}} while (input);return 0;
}

运行结果:

在这里插入图片描述

4. 什么是回调函数

我们先来捋一下刚刚改进代码的函数执行思路:
在这里插入图片描述

回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。
主调函数,也称为调用者函数,是指在程序中调用其他函数的那个函数。它通常包含了对被调用函数的调用语句,并负责传递参数、处理返回值以及控制函数间的流程。主调函数的作用是将任务分解为更小的部分,提高代码的复用性和模块化,使得程序结构更加清晰。在C++或Java等语言中,无论是直接调用还是通过指针或引用间接调用,都是由主调函数发起的。

这里的Add、Sub就是回调函数; calc就是主调函数
这里就是提到,后面会详细讲解;

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

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

相关文章

【Python 数据分析学习】Pandas的基础和应用(2)

题目 1 数据运算与分析1.1 算数和比较运算1.1.1 算数运算1.1.2 比较运算 1.2 数据排列1.3 统计分析1.3.1 基本的统计分析函数1.3.2 特殊的统计分析函数1.3.3 检查和处理空值 1.4 分组与聚合1.4.1 数据分组1.4.2 数据聚合 1.5 透视交叉表1.5.1 透视表1.5.2 交叉表 2 实战演练2.1…

Centos挂载和删除nfs

一、Centos挂载nfs 1、安装NFS客户端软件 sudo yum install nfs-utils 2、 创建一个挂载点目录 mkdir -p /mnt/nfs 注意:目录可以随意创建 3、永久挂载nfs 即系统在每次启动后自动挂载NFS共享 (1)编辑 /etc/fstab vim /etc/fstab (2)添加nfs <nfs_server_ip&…

音视频入门基础:AAC专题(3)——AAC的ADTS格式简介

一、引言 AAC&#xff08;Advanced Audio Coding&#xff09;有两种格式&#xff1a; 1.ADIF&#xff08;Audio Data Interchange Format&#xff0c;音频数据交换格式&#xff09;&#xff1a;整个流中只包含一个Header&#xff08;文件头&#xff09;&#xff0c;不能在任意…

爆品只是日百商家的表面“风光”

前不久&#xff0c;#大学生买爆台州商家的移动收纳筐#的话题上了热搜。现在的大学生相比以前讲究多了&#xff0c;虽然生活费没涨多少&#xff0c;但生活一定要精致。比如&#xff0c;在有限的预算内买各种收纳神器&#xff0c;把宿舍整理地井井有条。 爆品&#xff0c;往往成…

【2024SpringCloud教程】前言闲聊开篇简介

前言大纲 适合对象&#xff0c;从小白到熟手 前置知识&#xff0c;必要的前置基础知识 紧抓核心&#xff0c;与时俱进学最新&#xff0c;停更技术不用看 突出实战&#xff0c;让天下没有难学的技术 一、适合对象&#xff0c;从小白到熟手 两套课程 springCloud SpringCl…

90v转5v500MA内置mos芯片方案

在设计一个90V转5V500mA的DC/DC转换器方案时&#xff0c;可以考虑使用AH7550这款150KHz固定频率PWM降压&#xff08;降压&#xff09;DC/DC转换器。AH7550能够以高效率、低纹波和出色的线路和负载调节驱动0.4A负载&#xff0c;且需要最少数量的外部组件&#xff0c;使用简单&am…

css scrollbar-width: none 隐藏默认滚动条

.table-box{ flex: 1; overflow-y: scroll; scrollbar-width: none;} scrollbar-width: none; 隐藏默认滚动条

HAL库学习梳理——I2C

笔者跟着B站铁头山羊视频学习 STM32-HAL库 开发教程。下面对HAL库有关 I2C 课程知识和应用做一个梳理。 省流&#xff1a; uint8_t commands[] {0x00, 0x8d, 0x14, 0xaf, 0xa5};HAL_I2C_Master_Transmit(&hi2c1,0x78,commands,sizeof(commands)/sizeof(commands[0]) ,HA…

灌区信息化发展趋势展望

灌区信息化作为现代农业发展的重要组成部分&#xff0c;正逐渐成为提升水资源管理效率、保障粮食安全与促进农业可持续发展的关键途径。随着信息技术的飞速进步和智能化技术的广泛应用&#xff0c;灌区信息化的未来发展趋势展现出多维度、深层次的变革与创新&#xff0c;其发展…

基坑气膜:创新的绿色施工防护方案—轻空间

随着我国城市化进程的加快&#xff0c;建筑工地密集施工给城市居民带来了扬尘、噪音等环境问题。基坑气膜作为一种创新的绿色施工技术&#xff0c;正在成为解决这些问题的有效方案。该技术在降低环境污染、保障施工进度和提高施工安全性方面发挥着重要作用&#xff0c;逐渐受到…

深度学习张量变换操作利器 einops 基础实践

今天在一个项目调试的时候无意间报错&#xff1a; 以前其实并没有怎么多接触过einops&#xff0c;今天正好碰到了&#xff0c;就简单总结记录下。 解决上面的报错很简单&#xff0c;直接pip安装即可&#xff1a; einops 是一个用于操作张量的库&#xff0c;它提供了一种简洁且…

SpringBoot整合WebSocket实现消息推送或聊天功能示例

最近在做一个功能&#xff0c;就是需要实时给用户推送消息&#xff0c;所以就需要用到 websocket springboot 接入 websocket 非常简单&#xff0c;只需要下面几个配置即可 pom 文件 <!-- spring-boot-web启动器 --><dependency><groupId>org.springframewo…

springboot老年康复中心—计算机毕业设计源码27406

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出法&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤,采用Springboo框架建设老年康复中心信息管理系统。…

vue2基础系列教程之v-model及面试高频问题

v-model是表单组件里面的核心知识点&#xff0c;这个指令给我们写表单业务带来了很大的方便。 元素标签上的 v-model 指令用于双向绑定数据,它是一个语法糖&#xff0c;可以用于代替 v-bind:value 和 input 例如&#xff1a;<input v-model"message" placeholder…

用户洞察|从被动养老到主动康养,新康养人群的幸福生活新思路

图源&#xff1a;NewAgingPro团队访谈摄影 全龄康养&#xff0c;大势所趋 作者 | NewAgingPro团队 排版 | Lucy 前言 本文将从我国银发经济发展背景出发&#xff0c;结合AgeClub旗下的NewAgingPro新老年商业研究团队持续多年的用户需求调研及访谈分析&#xff0c;深度洞察…

OpenCV运动分析和目标跟踪(1)累积操作函数accumulate()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将一个图像添加到累积图像中。 该函数将 src 或其部分元素添加到 dst 中&#xff1a; dst ( x , y ) ← dst ( x , y ) src ( x , y ) if mask…

SQL Server小技巧之遍历日期

使用背景 一般项目中会遇到&#xff0c;求每日的日报这种&#xff0c;以及计算2个日期内的工作日&#xff0c;或者休息日可能会用到&#xff0c;计算休息日可以用额外的一个字段用来标记当前日期是否是休息日 遍历方式一 DECLARE StartDate DATE 2023-01-01, EndDate DATE …

SSM基于响应式的网上书店系统—计算机毕业设计源码27119

摘 要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理系统的实施在技术上已逐步成熟。管理系统是一个不断发展的新型学科&#xff0c;本文主要通过对响应式的网上书店系统的功能性需求分析&#xff0c;对系统的安全性和可扩展性进行了非功能性需求分析。在详细的…

【C++】详细介绍类的相关语法概念,this,默认成员函数,static,友元,内部类

目录 1. 类的基本概念 1.1 类的语法 1.2 类的访问限定符 1.3 类的两种定义方式 1.4 类的作用域 1.5 类的实例化 1.6 类对象的大小 2. this指针 2.1 概念 2.2 特性 2.3 面试题 3. 类的六个默认成员函数 3.1 构造函数 3.1.1 特性 3.1.2 默认构造函数 3.1.3 函数…

高效数据移动指南 | 如何快速实现数据库 MySQL 到 MongoDB 的数据同步?

在现代企业中&#xff0c;数据无处不在&#xff0c;贯穿于各个业务环节和系统之间。无论是跨系统的数据集成、多地域的数据协同&#xff0c;还是实时应用的数据同步&#xff0c;数据的一致性和及时性都至关重要。在数字化转型的过程中&#xff0c;如何确保不同系统、地域、设备…