文章目录
- 引入
- 1.利用转移表改进
- 2.什么是转移表
- 3.利用回调函数改进
- 4. 什么是回调函数
引入
函数指针数组的⽤途:转移表
举例:计算器的⼀般实现:
我们若用以前的代码实现:
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就是主调函数
这里就是提到,后面会详细讲解;