c语言:转移表的实现

时间:2024-02-29 20:26:59

Hello,宝子们!今天我们来模拟实现一下我们生活中的应用最频繁的工具:计算器,实现计算器有三种方式。
废话不多说,直接上代码,计算器的一般实现:

#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
	{
	    //首先一上来就打印菜单,下面进行选择,所以要用到do while 循环结构
		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;
}

像这样的代码看完之后有什么问题?虽然也不影响最后计算的结果,但是这样的代码是不是太冗余了,case里面重复的代码太多了,这还只有加减乘除四个选项,要是再多扩张几个选项呢,比如:&&,||,>>,<<等运算呢?所以这样的代码效率太低下,不推荐使用。
那有没有比较高效,不这么冗余的方法呢?当然了,这里就要用到我们前面所讲的函数指针数组了,如果还不知道函数指针数组是什么的话,可以看看我前面讲的这篇文章https://blog.csdn.net/weixin_66058866/article/details/136136008
相信聪明的你看完这篇文章,心里应该已经有答案了吧????
函数指针数组代码实现如下:

#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 }; 
	//为了跟菜单里的选项对应起来,需要在数组元素中的最前面加了一个元素,
	//这样就不至于出现当我们输入下标为1的元素时,访问的是sub这类问题了。
	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;
}

上面我们创建了函数指针数组,并且把加减乘除函数的地址都存放进去,然后想实现什么运算,直接通过下标的方式去调用对应的函数,这种方式就很好的解决了代码冗余的问题,而且如果你还想再扩张选项的时候,也不需要再像第一种方法那样麻烦了。
根据input下标,找到对应的函数,然后再调用对应的函数,这种方法有没有发现它像一个跳板一样,在做一个转移的动作,所以这种方法也被称为转移表
那么是否还有其他的方式呢?这时候我们就涉及到一种高级的玩法了。
首先来看代码:

#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;
}
void calc(int(*fp)(int x,int y))//使用函数指针来接收函数的地址
{
	int x=0;
	int y=0;
	int ret=0;
	printf("输⼊操作数:");
	scanf("%d %d", &x, &y);
	ret = fp(x, y);
	printf("ret = %d\n", ret);
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
	    //首先一上来就打印菜单,下面进行选择,所以要用到do while 循环结构
		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:
				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;
}

像这种实现方式,你会发现并没有在主函数里直接调用AddSubMulDiv等函数,而是把这些函数的地址传给了clac函数,然后再calc函数内部通过指针变量来调用calc指向的函数,这也是一种回调函数的机制,当然这种机制现在理解不了也没关系,在之后的深入理解指针(4)里面我会详细讲到哟!


创作不易,看完别忘了给博主一键三连哟!谢谢大家呀????