引入
函数指针数组的⽤途:转移表
举例:计算器的⼀般实现:
我们若用以前的代码实现:
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就是主调函数
这里就是提到,后面会详细讲解;