《IOS_C语言》函数指针、函数回调、动态排序、函数返回值是函数指针

一:函数指针(函数地址跟数组名类似,指向函数的首地址)

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);//返回结果





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大小小丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值