首页 > 其他分享 >C:回调函数的介绍-学习笔记

C:回调函数的介绍-学习笔记

时间:2024-08-27 23:26:54浏览次数:10  
标签:calc 函数 int 笔记 break ret printf 回调

前言:

本篇文章我们将继续指针相关知识:回调函数

希望大家在看完后能够有所收获!

回调函数

 定义与概念

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

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

假设有一个函数 A,它接收另一个函数 B 作为参数。当函数 A 在执行过程中达到某个特定条件时,它就会调用函数 B。这里的函数 B 就是回调函数。

是不是有点难以理解?我们先举个简单的实例来解释一下概念。

在该代码中,我们将add函数地址当作参数传递给test函数,然后通过函数指针pf找到add函数完成运算,在这个过程中,add函数就是回调函数。

 典型例题

我们来使用回调函数简化编写计算器程序的代码

简化前:

void menu()
{
	printf("************************\n");
	printf("**** 1.add   2. sub ****\n");
	printf("**** 3.mul   4. div ****\n");
	printf("******   0.exit    ******\n");
	printf("************************\n");
}
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;
}
#include <stdio.h>
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出计算器\n");
			break;	
         default:
	      printf("选择错误,请重新选择\n");
	      break;
		}
	} while (input);
	return 0;
}

通过上面的代码,我们能够完成计算器的基本功能实现,但是我们可以看到有大量的重复代码,导致代码冗余,怎么解决呢?在不使用回调函数的情况下。

我们是否可以尝试将相同的代码提出来?

这样看起来似乎完成了简化代码的操作,我们来测试一下、

可以发现,就算我们选择错误,也会让我们先输入两个操作数,这样在逻辑上就出现了问题,所以这样将相同的代码提出来的方法不可行。

那这里我们应该做呢?如何使用回调函数呢?

简化后:

void menu()
{
	printf("************************\n");
	printf("**** 1.add   2. sub ****\n");
	printf("**** 3.mul   4. div ****\n");
	printf("******   0.exit    ******\n");
	printf("************************\n");
}
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;
}
calc(int(*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
#include <stdio.h>
int main()
{
	int input = 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("退出计算器\n");
			break;	
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
		
	} while (input);
	return 0;
}

在上面代码中的calc函数,具有通用功能,可以计算 + - * / 四种运算,它通过接收传递过来的函数地址,来找到对应的函数,比如说将Add函数地址传递给calc函数,然后calc函数再通过函数指针pf找到函数Add完成加法运算。

 回调函数的作用

1.回调函数能够提高代码的复用性

  • calc函数可以被不同的运算函数调用,实现了代码的复用。无论是什么运算,只要符合函数指针的类型要求,都可以作为回调函数传递给calc进行运算。
  • 例如,如果在其他地方也需要进行类似的运算操作,可以直接调用calc函数,并传入相应的回调函数,而不需要重复编写输入处理和结果输出的代码。

2.回调函数的使用可以使得整个工程中有清晰的代码结构

  • menu函数负责展示菜单和接收用户输入,switch 语句根据用户输入决定调用哪个运算函数作为回调。而calc函数则专注于执行具体的运算操作,它并不关心具体的运算是什么,只需要接收一个函数指针作为参数,然后调用这个函数指针指向的回调函数进行运算。
  • 这种分离使得代码结构更加清晰,各个部分的职责明确,易于理解和修改。

结语:

本篇文章主要讲了回调函数的一些基本概念和例题介绍,后面随着小编学习的深入,会不断更新该模块的更多知识。

标签:calc,函数,int,笔记,break,ret,printf,回调
From: https://blog.csdn.net/2401_85010100/article/details/141242448

相关文章

  • HCIP笔记10-MPLS(1)
    MPLS:多协议标签交换多协议:可以基于多种不同的3层协议来生成2.5层的标签信息;包交换--包为网络层的PDU,故包交换是基于IP地址进行数据转发;就是路由器的路由行为;原始的包交换:数据包进入路由器后,路由器需要查询本地的路由表(RIB-路由信息数据库),再基于下一跳或者目标ip查询本地的A......
  • datawhale深度学习入门:task1学习笔记
    机器学习是一种人工智能的分支,它主要涉及通过经验和数据来训练计算机模型以自动处理任务或进行预测。这些模型可以利用算法和数学模型来分析和学习数据,然后使用这些知识来执行特定的任务,如图像识别、语音识别、自然语言处理、数据分类、趋势预测等。深度学习是人工智能(AI)中的......
  • 资料分析笔记
    一、统计术语基期:作为对比参照的时期现期:相对于基期的称为现期描述具体数值时称之为基期量和现期量增长量vs增长率增长量:现期量和基期量增长(或减少)的绝对值增长量是具体值,有单位增长量=现期量-基期量增长量有正负,负值代表减少量增长率:增长量和基期量的相对......
  • Datawhale X 李宏毅苹果书 AI夏令营 Task1.2 笔记
    《深度学习详解》3.2节中关于批量和动量的主要内容总结: 批量的概念:在深度学习训练过程中,数据不是一次性全部用于计算梯度,而是被分成多个小批量(batch),每个批量包含一定数量的数据。每个批量的损失函数用于计算梯度并更新模型参数。批量大小对梯度下降法的影响:两种极端情况:......
  • MySQL数据库(2)——DML、视图、函数
    目录1、DML——数据操作语言(DataManipulationLanguage)2、添加数据2.1语句添加2.2文件加载3、修改数据4、删除数据5、查询数据5.1DQL基本关键字及其说明 着重号SQL简单查询5.2别名查询5.3去重查询5.4单表查询算数运算符比较运算符逻辑运算符范围......
  • vue3 自定义hooks(组合式函数)
    什么是hooks自定义hooks是Vue3组合式函数的别称。在Vue应用的概念中,“组合式函数”(Composables)是一个利用Vue的组合式API来封装和复用有状态逻辑的函数。命名规范组合式函数约定用驼峰命名法命名,并以“use”作为开头。以便识别它们是可复用的逻辑单元。例如,u......
  • 字符串函数 (总篇章,全面解析)
    文章目录1.strlen函数函数的使用:strlen的模拟实现:分法1计数法:方法2递归法:分法3指针法:2.strcpy函数strcpy的使用:strcpy的模拟实现:3.strcat函数strcat函数的使用:strcat函数的模拟现实:4.strcmp函数strcmp函数的使用:strcmp函数的模拟实现:5.strncpy函数6.strncat函数7.s......
  • 初赛笔记(全面)
    计算时间复杂度 规则   斐波那契数列 表达式:F[1]=1, F[2]=1, F[n]=F[n-1]+F[n-2](n>=3)如果是递推去计算,也就是一个for循环搞定,肯定是O(n)的,因为每一项的值可以通过前面两项的值得到,属于是记忆化了所以啊,计算复杂度一定要注意是否有记忆化  那么如果......
  • 数据结构学习笔记
    李超线段树学习笔记模板传送门从模板题就能看出来嗷,李超线段树非常牛逼。\bx从名字中就能看出来嗷,这玩意儿是个线段树。那么考虑在线段树上维护一堆线(一次函数)。对于每个点,存所有线中,使这个线段$mid$的点的线。对于加入一个点,根节点递归,扫到一个点时,若这个点在$mid$......
  • C++系列学习笔记
    #include<iostream>#include<iomanip>usingnamespacestd;//namespace:命名空间的关键字//std:系统的关键字intmain(){cout<<"输入"<<endl<<"int,char,double"<<endl;intnum=0;ch......