一.函数指针数组
1概念: 数组是一个存放相同类型数据的存储空间,把函数地址存放在一个数组中,那么这个数组叫做函数指针数组。其语法为 int(*parr1[10]();
通过前面的课程的学习,我们已经掌握了函数指针的用途,要想在此基础上理解函数指针数组,必须从函数指针来进行拓展,下面有一例函数指针的用途,试试看你有没有更好的方法对下面例子进行改进。
#include<stdio.h>
void menu()
{
printf("**************************************\n");
printf("*****1.add 2.sub********************\n");
printf("*****3.mul 4.div*******************\n");
printf("*****0.exit***************************\n");
}
int Add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int mul(int x,int y)
{
return x*y;
}
int div(int x,int y)
{
return x/y;
}
int main()
{
int input = 0;
int ret = 0;
d0
{
menu();
printf("请选择:>\n");
scanf("%d",&input);
printf("请输入2个操作数:>");
scanf("%d %d",&x,&y);
switch(input)
{
case 1:
ret=Add(x,y);
printf("%d\n",ret);
break;
case 2:
ret=sub(int x,int y);
printf("%d\n",ret);
break;
case 3:
ret= mul(int x,int y);
printf("%d\n",ret);
break;
case 4:
ret= div(int x,int y);
printf("%d\n",ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n);
break;
}
}while(input);
return 0 ;
}
很明显上述代码看起来不太简洁,试着优化一下代码使其看起来简单明了。在选择加减乘除代码中可以放在一个函数中进行运行。
#include<stdio.h>
void menu()
{
printf("**************************************\n");
printf("*****1.add 2.sub********************\n");
printf("*****3.mul 4.div*******************\n");
printf("*****0.exit***************************\n");
}
int Add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int mul(int x,int y)
{
return x*y;
}
int div(int x,int y)
{
return x/y;
}
void clc(int(*pf)(int,int)
{
int x = 0;
int y = 0;
int ret = 0;
scanf("%d %d",&x,&y);
ret = pf(x,y);
printf("%d\n,ret);
}
int main()
{
int input = 0;
d0
{
menu();
switch(input)
{
case 1:
clc(Add);
break;
case 2:
clc(sub);
break;
case 3:
clc(mul);
break;
case 4:
clc(div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n);
break;
}
}while(input);
return 0 ;
}
上述代码通过把函数的地址传过去用函数指针int(*pf)(int ,int)接收,通过pf再次找到需要运行的函数使其相加减。
上述函数的返回类型,参数都一样,所以可以利用函数指针数组来进行在一次的优化。
#include<stdio.h>
void menu()
{
printf("**************************************\n");
printf("*****1.add 2.sub********************\n");
printf("*****3.mul 4.div*******************\n");
printf("*****0.exit***************************\n");
}
int Add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int mul(int x,int y)
{
return x*y;
}
int div(int x,int y)
{
return x/y;
}
int main()
{
int (*pf)(int,int)=Add;
int (*arr[4](int,int)={Add,sub,mul,div};
int i= 0;
for(i=0;i<4;i++)
{
int ret = arr[i](4,8);
printf("%d",ret);
}
return 0;
}
二,回调函数
回调函数就是一个通过函数指针调用的函数,如果你把函数指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数,回调函数不是由该函数的实现方式直接调用,而是在特定的事件或条件发生时由另一方调用的,用于该事件或者条件的响应。
我们先回想学数组时写的冒泡排序,冒泡排序可以快速进行排序,但只能对整数进行快排,如果对于浮点数等非整数快排那么冒泡排序则不能用,能不能在冒泡排序的基础上进行改进使其快速进行非整数的快排。
冒泡排序的代码:
#include<stdio.h>
bubble_sort(int arr[],int sz)
{
int i = 0;
for(i=0;i<sz-1;i++)
{
int j = 0;
for(j=0;j<sz-1-i;j++)
{
if(arr[j]>arr[j+1]
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
int main()
{
int arr[]={9,8,7,6,5,4,3,2,1,0};
int sz = sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr,sz);
for(i=0;i<sz;i++)
{
printf("%d,arr[i};
}
return 0;
}
想达到冒泡排序的功能,库函数qsort可以不单单为整数排序,它的功能十分强大。要想了解该函数可以打开MSDN查找该函数的功能。其结果如下:
void*base:起始位置
size_tnum:元素个数
width:元素大小(字节)
const void*el:第一个元素
const void*e2:第二个元素
int cmp_int(const void*e1,const void*e2)
{
return (*(int*)e1-*(int*)e2);
}
int main()
{
int arr[]={9,8,7,6,5,4,3,2,1,0};
int sz = sizeof(arr)/sizeof(arr[0]);
qsort(arr,sz,sizeof(arr[0]),cmp_int);
for(i=0;i<sz;i++)
{
printf("%d,arr[i};
}
return 0;
}
说明:return (*(int*)e1-*(int*)e2); 其中把void*e1和e2强制类型转换为int*,因为void*是无具体类型的指针,可以接收任意类型的地址,所以不能用解引用操作,也不能+-整数。