C语言 指针高级:函数回调之动态调用

函数回调

#import <Foundation/Foundation.h>
typedef struct{
    char name[20];
    char sex;
    int age;
    int score;
    
}Student;
void printfStudent(Student *p,int count){
    for(int i=0;i<count;i++){
        printf("%s,%c,%d,%d\n",p[i].name,p[i].sex,p[i].age,p[i].score);
    }
}
//函数回调第一步:声明关键点的函数
typedef BOOL (*PFUN)(Student s1,Student s2);
//函数回调第二步1:实现函数1
BOOL bijiaoAge(Student s1,Student s2);
BOOL bijiaoAge(Student s1,Student s2){
    return s1.age>s2.age;
}
BOOL bijiaoScore(Student s1,Student s2);
BOOL bijiaoScore(Student s1,Student s2){
    return s1.score>s2.score;
}
BOOL bijiaoName(Student s1,Student s2);
BOOL bijiaoName(Student s1,Student s2){
    return strcmp(s1.name, s2.name)>0 ? YES : NO ;
}
//函数回调第二步2:实现函数2
void paixu(Student *p,int count,PFUN st );
void paixu(Student *p,int count,PFUN st ){
//冒泡排序,从小到大排列。
    for(int i=0;i<count-1;i++){
        for(int j=0;j<count-1-i;j++){
            if (st(p[j], p[j+1]))
            {
//结构体类型可以整体赋值。
                Student temp1=p[j];
                p[j]=p[j+1];
                p[j+1]=temp1;
            }
        }
    }
}
int main(int argc, const char * argv[]) {
    Student stus[3]={
        {"zhangsan",'m',23,89},
        {"lisi",'f',21,95},
        {"wangwu",'m',25,92}
    };
//这里传的两个参数,第一个参数不要用&stus,要用stus.数组做指针的参数
    printfStudent(stus, sizeof(stus)/sizeof(stus[0]));
    printf("=====================\n");
//函数回调第三步:函数回调
    paixu(stus, sizeof(stus)/sizeof(stus[0]),bijiaoName);
    printfStudent(stus, sizeof(stus)/sizeof(stus[0]));
    return 0;
}
//函数指针数组
/*
 int (*p[3])(int,int)={0};
 可改为:
 typedef int (*PFUN)(int,int);
 PFUN p[3]={0};
 p[0] = maxValue;
 p[1] = sum;
 */

//返回值是函数指针
/*
int (*functionName(int a))(int,int);
可改为:
typedef int (*PFUN)(int,int);
PFUN functionName(int a);
*/
//动态调用
/*
动态调用是系统普遍支持的技术
要实现动态调用需要一个对应表
例如:使用函数名的字符串调用函数
    函数名         函数指针
    "max"        "maxValue"
    "min"        "minValue"
    "avg"        "avgValue"
第一步定义一个结构体,里面放表对应关系的字段。
typedef struct nameFunctionPair{
    char name[30];
    PFUN function;
 }NameFunctionPair;
第二步用结构体数组定义一个表的对应关系。
NameFunctionPair nfs[3]={
 {"max",maxValue},{"min",minValue},{"avg",avgValue}
 };
void
第三步动态调用
PFUN getFunctionWithName(char *name);
PFUN getFunctionWithName(char *name){
    for(int i=0;i<3;i++){
        if(strcmp(nfs[i].name,name)==0){
            return nfs[i].function;
        }
    }
    return maxValue; //返回一个默认值,以防找不到而出错。
 }
int getValue2(int x,int y,char *functionName);
int getValue2(int x,int y,char *functionName){
PFUN p=getFunctionWithName(functionName);
    return p(x,y);
 }

主函数中调用: getValue2(10,20,"sum");
*/




举例1

#import <Foundation/Foundation.h>
 //声明和实现运算函数
int sumValue(int x,int y);
int sumValue(int x,int y){
    return x+y;
}
int avgValue(int x,int y);
int avgValue(int x,int y){
    return (x+y)/2;
}
int maxValue(int x,int y);
int maxValue(int x,int y){
    return (x>y)?x:y;
}
//关键点1:定义一个“PFUN”作为变量的函数指针类型
typedef int (*PFUN)(int,int);
//关键点2:定义结构体,并把表的对应关系用结构体数组形式列举出来
typedef struct nameFunctionPair{
    char name[30];
    PFUN function;
}NameFunctionPair;
NameFunctionPair nfs[3]={
    {"sum",sumValue},
    {"avg",avgValue},
    {"max",maxValue}
};
//关键点3:声明和实现一个返回值为函数指针类型的函数(获取函数名)。
//注意:设置一个默认返回值,否则程序运行若找不到函数名会出错
PFUN getFunctionWithName(char *name);
PFUN getFunctionWithName(char *name){
    for(int i=0;i<3;i++){
    if(strcmp(nfs[i].name, name)==0)
        return nfs[i].function;
    }
    return maxValue;
}
//关键点4:定义被调用函数,供调用函数调用(被调用函数)。
int getValue2(int x,int y,char *functionName);
int getValue2(int x,int y,char *functionName){
    PFUN p=getFunctionWithName(functionName);
    return p(x,y);
}
int main(int argc, const char * argv[]) {
    printf("%d",getValue2(50, 20, "sum"));
    printf("\n");
//    return 0;
}




举例2:

/*
 动态调用作业:
 动态函数调用实现下列操作,输入2个数以及操作符计算结果。
 @求最大公约数,$求最小公倍数,-求差,+求和 等等
 */
#import <Foundation/Foundation.h>
#define N 4
//求最大公约数函数:
int maxCommonDivisors(int x,int y);
int maxCommonDivisors(int x,int y){
    int temp=(x<y?x:y),max=1;
    for(int i=1;i<=temp;i++){
    if((x%i==0)&&(y%i==0))
        max=i;
    }
    return max;
}
//求最小公倍数函数:
int minCommonMultiple(int x,int y);
int minCommonMultiple(int x,int y){
    int temp=maxCommonDivisors(x,y);
    return x*y/temp;
}
//求差函数
int minusValue(int x,int y);
int minusValue(int x,int y){
    return x-y;
}
//求和函数
int sumValue(int x,int y);
int sumValue(int x,int y){
    return x+y;
}

//定义一个函数指针类型
typedef int (*PFUN)(int,int);

//定义一个结构体存放对应关系表
typedef struct corresponding{
    char name[30];
    PFUN founction;
}Corresponding;
Corresponding cp[N]={
    {"@",maxCommonDivisors},
    {"$",minCommonMultiple},
    {"-",minusValue},
    {"+",sumValue}
};
//声明和实现一个函数,根据字符串获取函数名,返回值为函数指针类型。
PFUN getFunctionWithName(char *name);
PFUN getFunctionWithName(char *name){
    for(int i=0;i<N;i++){
    if(strcmp(cp[i].name,name)==0)
        return cp[i].founction;
    }
    return maxCommonDivisors;//默认调用最大公约数
}
//声明和实现调用函数
int getValue(int x,int y,char *functionname);
int getValue(int x,int y,char *functionname){
    PFUN p=getFunctionWithName(functionname);
    return p(x,y);
}
int main(int argc, const char * argv[]) {
//    printf("最大公约数为:%d\n",maxCommonDivisors(18,9));
//    printf("最小公倍数为:%d\n",minCommonMultiple(18,27));
    int x,y;
    char c;
    printf("请输入两个整数用空格隔开:");
    scanf("%d %d",&x,&y);
    getchar();
    printf("请输入计算符号(最大公约数输入 @,最小公倍数输入 $):");
    scanf("%c",&c);
    
//    printf("计算结果为:%d\n",getValue(x,y,&c)); //*****这中形式为啥不行******

    switch(c){
        case '$':
            printf("最小公倍数计算结果为:%d\n",getValue(x,y,"$"));
            break;
        case '@':
            printf("最大公约数计算结果为:%d\n",getValue(x,y,"@"));
            break;
        case '-':
            printf("它们的差计算结果为:%d\n",getValue(x,y,"-"));
            break;
        case '+':
            printf("它们的和计算结果为:%d\n",getValue(x,y,"+"));
            break;
        default:
            printf("输入运算符为非法字符,不能参与运算!\n");
            break;
    }

    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值