一:函数指针(函数地址跟数组名类似,指向函数的首地址)
1、函数指针的定义(没有固定的类型,只有某一类的函数指针)
格式:int maxValue(int a,int b);
int (*p)(int a,int b)=NULL;
p是变量,其他都是他的类型,参数是两个int型组成,返回值是一个int型,并且赋初值为NULL即是=0;
使用时,直接把函数名换成指针名
p=maxValue;
int m=p(3,6);//这里实际是=maxValue(3,6);
课上练习1:定义一个函数指针和使用:
(1)函数定义:
void printHello()
{
printf("Hello!");
}
(2)函数指针的使用:
void(*p)()=NULL;//先置空值
p=printHello;//令指针名=函数名
p();//相当于函数printHello()调用函数
二:函数回调
与函数的调用不一样,因为使用指针函数回调是动态的调用,而函数嵌套调用已经确定的,静态调用。(指指针作为参数)
格式:int getValue(int a,int b,int(*p)(int,int));
int value=getValue(3,5,maxValue);getValue执行过程中调用maxValue函数
课上练习(重点理解):定义两个函数,一个求最大值,一个求和,输入max或者sum,分别求3,5的最大值和和,提示定义一个函数指针,很据输入的内容指向不同函数,最后一次调用完成。
(1)函数定义:
int getmax(int a,int b)
{
return max=a>b?a:b;
}
int getsum(int a,int b)
{
return sum=a+b;
}
(2)main函数里面的指针函数的调用
int(*p)(int a,int b)=NULL;由于上面的连个函数的类型和形参以及返回值都一样,所以之定义一个指针函数就可以了。
char str[30]={0};//用于存放客户输入的需求
printf("请输入sum或者max\n");
scanf("%s",str);
if(strcmp(str,"sum")==0){//根据输入的不同使得函数指针名等于不同的函数名,从而实现执行不同的函数操作
p=getsum;
}else if(strcmp(str,"max")==0){
p=getmax;
}
int result=p(5,7);/调用函数,并且结果用一个整型的变量来装结果。
printf("%s",ressult);
//课上练习3:
//实现函数的动态调用
(1)函数定义
int getValue(int a,int b,int(*p)(int a,int b))
{
return p(a,b);//实际上getValue()函数就是根据指针函数所调用的函数而输出结果的
}
(2)函数指针的使用
int result=getValue(5,6,getmax)//实际上的意思p=getmax
printf("%d",result);
//课上练习4:写⼀一函数查找成绩90分以上的学员,使⽤用回调函数在姓名后加”⾼高富帅”。
(1)函数的定义以及结构体的定义
typedef struct stu
{
char name[30];
float score;
}Student;
//拼接函数
void addName(char*str1,const char*str2)
{
strcat(str1,str2);
printf("%s\n",str1);
}
//在数组中寻找满足条件的使用指针函数p调用拼接函数
void findScoreAddString(Student*stus,int count,void(*p)(char*str1,char*str2))
{
for(int i=0;i<count;i++){
if(stus[i]>90){
p(stus[i],"高富帅");
}
}
}
//打印学生信息函数
void print(Student *stus,int count)
{
for(int i=0;i<count;i++){
printf("%s,%.2f",stus[i].name,stus[i].score);
}
}
(2)main函数里面使用函数指针达到函数回调作用
Student stu1={"zhangsan",98};
Student stu2={"hahahhah",36};
Student stus[2]={stu1.stu2};
print(stus,2);
findScoreAddString(stus,2,addstring)或者
void(*p)(char*,const char*)=NULL;
p=addstring;
findScoreAddString(syus,2,p);
print(stus,2);
三:动态排序
以前学的是静态排序,把所有排序写好,根据客户的需求进行调用和排序,如淘宝商城根据不同的需求进行排序,使用函数指针进行指向。
typedef BOOL(*PFUN)(int ,int);//加了typedef(取别名,这里就表示PFUN就不仅仅是一个指针名,更是指返回值是bool型,形参是两个int型的函数指针,也表示这样的类型,即:BOOL(*PFUN)(int,int)这一串等价于PFUN类型,下次使用就不需要再次定义一大串BOOL(*PFUN)(int,int),只需要类型PFUN+变量名就可以了)
如://如:动态排序函数声明(下面直接声明p的类型是BOOL类型返回值,参数是两个形参)
// void sortArray(int * arr,int count,PFUN p);//PFUN p是核心
课上练习:根据客户的需求对学生信息进行排序,排序的办法有根据姓名升序、降序排序,根据成绩的升序、降序排序
首先定义一个结构体数组
typedef struct stu
{
char name[30];
float score;
}Student;
//按照姓名的升序排序
void compareByNameUp(Student stu1,Student stu2)
{
if(strcmp(stu1.name,stu2.name)>0){
return 1;表示满足if(1)的条件,在排序那里则会执行交换位置进行升序排序
}else{
return 0;
}
}
//按照姓名的降序排序
void compareByNameLow(Student stu1,Student stu2)
{
if(strcmp(stu1.name,stu2.name)<0){
return 1;表示满足if(1)的条件,在排序那里则会执行交换位置进行升序排序
}else{
return 0;
}
}
//按照成绩升序排序void compareByScoreUp(Student stu1,Student stu2)
{
return stu1.score>stu2.score;
}
//按照成绩降序排序
void compareByScoreUp(Student stu1,Student stu2)
{
return stu1.score<stu2.score;
(3)定义函数指针(由于以上的返回都是一样的bool类型,形参都是结构体变量)
typedef BOOL(*p_fun)(Student stu1,Student stu2);//这一串的类型,可以直接用p_fun表示类型
(4)数组排序函数:
void sortArray(Student *stus,int count ,p_fun p)
{
for(int i=0;i<count-1;i++){
for(int j=0;j<count-1-i;j++){
if(p(stus[j],stus[j+1])){//根据传进来的不同函数指针,执行不同的函数
Student temp=stus[j];//交换的是学生结构体变量
stus[j]=stus[j+1];
stus[j+1]=temp;
}
}
}
}
(5)main函数里面调用以上函数
Student stu1={"zhangsan",90.0};
Student stu2={"lisi",68.8};
Student stu3={"lihahha",100};
Student stus[3]={stu1,stu2,stu3};
int count=3;
//函数调用,根据客户输入(用switch case)
int number=0;
printf("按照姓名升序请按1\n按照姓名降序请按2\n按照分数升序请按3\n按照分数降序请按4\n");
scanf("%d",&number);
p_fun p;
switch(number){
case 1:
p=compareByNameUp;
break;
case 2:
p=compareByNameLow;
break;
case 3:
p=compareByScoreUp;
break;
case 4:
p=compareByScoreLow;
break;
default:
printf("您输入错误,请输入1~4\n");
break;
}
//排序函数调用
sortArray(stus,count,p);//调用上面的动态排序函数,p再动态根据客户输入的选择而调用不同的函数
print(stus,count);//调用打印学生信息的函数
四:函数返回值是函数指针
//4、函数返回值是函数指针
//如:百度地图
// PFUN getFunctionByName(char*name);//返回的就是PFUN的函数指针类型的
//课上练习知识点4:通过字符串来获取函数功能
/*********通过字符串查找要执行对应的功能*********************/
(1)各种功能函数的定义
int max(int a,int b)
{
return a>b?a:b;
}
int sum(int a,int b)
{
return a+b;
}
int muli(int a,int b)
{
return a*b;
}
int sub(int a,int b)
{
return a-b;
}
(2)定义指针函数(上面的函数都是同类型的)
typedef int(*p_fun)(int ,int);//直接把这种类型定义成p_fun
(3)定义功能结构体,让输入的函数名name与函数名建立一一对应关系
typedef struct function
{
char name[30];
p_fun fun;//定义函数指针的变量名为fun
}Function;
//定义全局功能结构体数组(并且只能这么定义)
Function function[]={{"max",max},{"sum",sum},{"muli",muli},{"sub",sub}};
//使得函数名和输入的名字建立一一对应关系
//通过字符串获取对应的函数指针的函数,返回值是函数指针,因此定义返回值也是函数指针类型的
p_fun getFunctionByName(char*name)
{
for(int i=0;i<sizeof(function)/sizeof(Function),i++){//sizeof(function)计算整个数组所占用的字节数,sizeof(Function)计算一个结构体所占的字节,sizeof(function)/sizeof(Function)表示计算出有多少个功能数组
if(strcmp(function[i].name,name)==0){
return function[i].fun;
}
}
return 0;
}
(4)通过获取出来的函数,实现对应函数的功能
int getResult(int a,int b,p_fun fun)
{
if(fun==0){
return 0;
}else{
return fun(a,b);//调用对应的函数功能,并且返回对应处理后的值
}
}
(5)主函数里面
char name[30]={0};
printf("please input a name,sum或者max或者muli或者sub\n");
scanf("%s",name);
p_fun fun=getFunctionByName(name);//找函数名
int result=getResult(3,5, fun);//根据指针函数名找到结果
printf("result=%d\n",result);//返回结果