函数指针数组应用:转移表

转移表

目录

  • 一般实现
  • 函数指针数组实现
  • 回调函数实现

1、一般实现

让我们先来看下计算器的一般实现:

1、构建框架

int main()
{
	int x,y;//初始化两个操作数
	int ret = 0;
	int input = 1;
	do
	{
		scanf("%d", &input);
		switch(input)
		{
		
		}
	} while ( );
	return 0;
}

2、打印菜单

可以构建一个menu函数,在之前扫雷的案例中已经涉及。

void menu()
{
		printf("***********************\n");
		printf("**** 1.add   2.sub ****\n");
		printf("**** 3.mul   4.div ****\n");
		printf("**** 0.exit        ****\n");
		printf("***********************\n");
		printf("请选择\n");
}

3、完善分支

首先,需要输入一个input,根据input不同的值来判断应该进入switch的哪一个分支。

  • 当input的值为1时,做加法运算。
  • 当input的值为2时,做减法运算。
  • 当input的值为3时,做乘法运算。
  • 当input的值为4时,做除法运算。
  • 当input的值为0时,退出计算器。
  • 当input的值不为以上值时,需要重新输入。

4、补齐对应函数

随后我们以加法为例:

int add(int a, int b)
{
 	return a + b;
}
switch(input)//input非0时为真,进入switch内部
{
	case 1:
		printf("输⼊操作数:");
 		scanf("%d %d", &x, &y);
 		ret = add(x, y);//调用对应函数
 		printf("ret = %d\n", ret);
 		break;
}

5、代码呈现

#include <stdio.h>
void menu()
{
	printf("***********************\n");
	printf("**** 1.add   2.sub ****\n");
	printf("**** 3.mul   4.div ****\n");
	printf("**** 0.exit        ****\n");
	printf("***********************\n");
	printf("请选择\n");
}
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
 	{
		menu();
 		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);//以input作为控制循环的条件十分巧妙,当input的值为0时,正好不再循环
 return 0;
}
 

但是我们不难发现,这种写法十分的复杂且出现了许多段相似的代码,能不能使它们精简一些呢?

这时我们就可以使用函数指针数组,将函数指针放到一个数组中,当我们需要调用其中的函数时,只要访问这个函数指针数组,取出所需函数的地址,对其进行调用,可以大幅精简代码。

2、函数指针实现

首先,我们可以创建一个函数指针数组,把可能需要使用的函数地址存入其中。

int (*pf[5])(int x, int y) = {0, add, sub, mul, div};

这里在开头放入0,是为了保证函数地址在数组中的下标与对应input值相同,方便后面我们调用对应函数。
在这里插入图片描述

这时,我们就可以摒弃复杂的switch语句,而使用if-else语句来实现转移表。代码如下(if-else语句部分):

if (input >= 1 && input <= 4)
{
	int a, b = 0;
	printf("请输入两个操作数\n");
	scanf("%d %d", &a, &b);
	ret = (*p[input])(a, b);//input对应数组下标,调用对应函数
	printf("%d\n", ret);
}
else if (input == 0)
{
	printf("退出计算器\n");
}
else
{
	printf("输入错误,重新输入\n");
}

3、回调函数实现

那么,我们可不可以不使用函数指针数组,而起到简化代码的效果呢?
答案是:可以。
我们可以通过回调函数来达到这个效果。

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

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

**我们可以构建一个无返回值的calc函数,接收一个函数指针,通过该指针调用对应函数,达到化繁为简的效果。**代码如下(calc函数+主函数部分):

void calc(int(*pf)(int x,int y))
{
	int ret = 0;
	int x,y;
	printf("输入操作数:");
	scanf("%d %d",&x,&y);
	ret = pf(x,y);
	printf("ret = %d\n",ret);
}
int main()
{
	menu();
 	int input = 1;
 	do
 	{
 		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;
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值