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

引入

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

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就是主调函数
这里就是提到,后面会详细讲解;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比特在路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值