//函数指针
//回调函数
//利用函数指针以及回调函数,实现动态函数
main.m中程序:
//
// main.m
// Lesson_15-8-11
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Sort.h"
//两个数中的最大值
int maxValue(int a,int b);
int (*p)(int a,int b);//函数指针
int maxValue(int a,int b){
return a>b?a:b;
}
//求和
int sumTwoNumber(int a,int b);
int sumTwoNumber(int a,int b){
return a+b;
}
//给一个指针指向其他函数
int getValueOfOperation(int a,int b,int (*p)(int ,int ));
int getValueOfOperation(int a,int b,int (*p)(int ,int )){
int result=p(a,b);
return result;
}
//数组升序排列
void sortAscending(int array[],int n);
void (*point_arrayInt)(int array[],int n);
void sortAscending(int array[],int n){
//---第一种 数组一般排序
int temp=0;
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
if (array[j]>array[j+1]) {
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
printf("使用一维数组的一般形式实现升序排序:\n");
for (int i=0; i<n ; i++) {
printf("%d\t",array[i]);
}
printf("\n");
//---第二种 指针排序
int temp_point=0;
int *point=NULL;
point=array;
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
if (point[j]>point[j+1]) {
temp_point=point[j];
point[j]=point[j+1];
point[j+1]=temp_point;
}
}
}
printf("使用指针来实现一维数组的升序排序:\n");
for (int i=0; i<n ; i++) {
printf("%d\t",point[i]);
}
printf("\n");
}
//打印hello
void printHello();
void (*point_Print)();
void printHello(){
printf("hello beijing!\n");
}
int main(int argc, const char * argv[]) {
//函数:实现某特定功能的一段代码。
#pragma mark 函数指针
//函数指针---》是一个函数类型的指针
//===>函数指针:指向函数首地址的指针。可以通过函数指针调用指向的函数。
//定义===》返回值类型 (*函数指针名) (参数1,参数2);
//函数指针名=函数名;
//函数名也是地址。函数名指向存代码的那段内存的首地址。
//===>练习1:
int a=4;
int b=9;
p=maxValue;
int max=p(a,b);
printf("最大值:%d",max);
printf("\n=================================================\n");
//练习2:
int array_Int[10]={0};
for (int i=0; i<10; i++) {
array_Int[i]=arc4random()%(100-80+1)+80;
printf("%d\t",array_Int[i]);
}
printf("\n");
point_arrayInt=sortAscending;
point_arrayInt(array_Int,10);
//函数指针类型:返回值类型(*)(参数类型)
//练习3:
//定义一个函数:void PrintHello();
printf("\n===============================================\n");
point_Print=printHello;
point_Print();
//练习4、
//定义两个函数,求最大值、求和,输入maxValue或sum分别对两个数3,5求值。定义一个函数指针,根据输入的内容指向不同的函数,一次调用。
int num1=3,num2=5;
char operator[10]={0};
printf("要进行的操作:\n");
scanf("%s",operator);
getchar();
if (strcmp(operator, "maxValue")==0) {
p=maxValue;
//分开写
//p!=NULL 为了程序的健壮性
if (p!=NULL){
int maxValue=p(num1,num2);
printf("%d和%d中的最大值:%d\n",num1,num2,maxValue);
}
}else if (strcmp(operator, "sum")==0){
p=sumTwoNumber;
if (p!=NULL) {
int sumValue=p(num1,num2);
printf("%d+%d=%d\n",num1,num2,sumValue);
}
}else{
printf("输入有误\n");
}
//总体写
if (p!=NULL) {
int returnValue=p(2,4);
printf("2,4进行%s运算后返回的值:%d\n",operator,returnValue);
}
//定义一个含有函数指针的形参的函数,实现加减乘除
char operator1[10]={0};
printf("要进行运算的函数名:\n");
scanf("%s",operator1);
getchar();
if (strcpy(operator1, "sumTwoNUmber")==0) {
p=sumTwoNumber;
}else if (strcpy(operator1, "maxValue")==0){
p=maxValue;
}
if (p!=NULL) {
int result=getValueOfOperation(num1, num2, p);
printf("%d和%d进行%s运算后的结果:%d\n",num1,num2,operator1,result);
}
#pragma mark 回调函数
//回调过程:在getValueOfOperator执行过程中,通过传入的参数(函数指针),调用执行某个函数。
//回调函数:在函数执行过程中,被函数指针调用的函数。(名词)
//函数回调:调用回调函数的 操作。---操作(动词)
//练习5、
//写一个函数查找成绩90分以上的学员,使用回调函数在姓名后面加上“高富帅”。
//1、新建一个文件夹
//2、声明结构体类型(姓名,性别,年龄,分数);定义结构体数组;声明,定义函数实现查找成绩90分以上的学员。
//3、提示:1)回调函数:在姓名后加高富帅。2)输出所有的学生信息,写成函数。
Student stu[3]={
{"yibella",'m',22,98.5},
{"jack",'f',23,95},
{"captain",'f',34,89}
};
void (*point)(Student stu[],int n)=printMessages;
pp p1=addPostfix;
findScoreOver90(stu, 3, point,p1);
//最原始的排序方式
void (*pointSort)(Student stu[],int n)=printAllInformation;
sortAscendByAge(stu, 3, pointSort);
sortAscendByName(stu, 3, pointSort);
sortAscendByScore(stu, 3, pointSort);
#pragma mark 动态函数
printf("\n==================================================\n");
printf("动态函数指针分配:\n");
//进化第一次----程序员可以在应用程序中动态的选择要执行的函数
BOOL (*pointSortByBOOL)(Student stu1,Student stu2);
pointSortByBOOL=compareStudentByAge;
sortStudent(stu, 3, pointSortByBOOL);
//进化第二次----用户可以自己控制功能,实现动态匹配执行的函数
//定义结构体数组
FunctionList list[3]={
{"name",compareStudentByName},
{"age",compareStudentByAge},
{"score",compareStudentByScore}
};
//输入执行的函数名
char _names[10]={0};
printf("输入你要执行的函数名(age,name,score):\n");
int aa=0;
scanf("%d",&aa);
scanf("%s",_names);
getchar();
//定义一个函数指针变量
POINT point_names=NULL;
//调用一个返回函数指针的函数
point_names=judgeFunction(_names, list, 3);
if(point_names!=NULL){
//此时的point_names已经前面返回的函数名,调用排序函数
sortStudent(stu, 3, point_names);
}
return 0;
}
自定义文件Student=====》
Student.h
//
// Student.h
// Lesson_15-8-11
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef struct Student{
char _names[20];
char _sex;
int _age;
float _score;
}Student;
//为void (*point)(Student stu[],int n)取一个别名 point
typedef void (*point)(Student stu[],int n);
//取别名
typedef void (*pp)(char *point);
//取别名
typedef void (*point_postfix)(char *point);
//=====================================================
//声明查找成绩在90分以上的函数
void findScoreOver90(Student stu[],int n,point point,pp p);
//声明打印学员信息的函数
void printMessages(Student stu[],int n);
//声明为满足条件的学员名字添加后缀的函数
void addPostfix(char *point);
Student.m
//
// Student.m
// Lesson_15-8-11
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//
#import "Student.h"
//实现查找成绩在90分以上的学员
void findScoreOver90(Student stu[],int n,point point,pp p){
int ScoreLimit=90;
//用来存储成绩90分以上的学员结构体数组。
Student stuTemp[10]={0};
//记录90分以上的学员的人数。
int count=0;
for (int i=0,j=0; i<n ; i++) {
//遍历,找到成绩90分以上的学员,并把名字后加 高富帅。
if (stu[i]._score>ScoreLimit) {
stuTemp[j]=stu[i];
//下面是两种加后缀的方法
//方法一 ====》是利用回调函数实现功能
p(stu[i]._names);
//方法二 ====》是直接加后缀
// strcat(stu[i]._names, "高富帅");
p(stuTemp[j]._names);
// strcat(stuTemp[j]._names, "高富帅");
j++;
count++;
}
}
//回调函数的应用
//传过去的结构体数组是成绩是90分以上的。
// point(stuTemp,count);
//注释掉的是用来输出成绩90分以上的学员的信息。
point(stu,n);
}
void printMessages(Student stu[],int n){
//输出全部的学员的信息
for (int i=0; i<n ; i++) {
printf("%s\t\t%c\t%d\t%.2f\n",stu[i]._names,stu[i]._sex,stu[i]._age,stu[i]._score);
}
printf("\n============================================\n");
//可以只输出成绩在90分以上的学员的信息
// for (int i=0; i<n ; i++) {
// printf("%s\t\t%c\t%d\t%.2f\n",stu[i]._names,stu[i]._sex,stu[i]._age,stu[i]._score);
// }
}
//给满足条件的名字加后缀
void addPostfix(char *point){
strcat(point, "高富帅");
}
自定义的Sort文件======》
Sort.h
//
// Sort.h
// Lesson_15-8-11
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Student.h"
//第一种:===》最原始的分个排序
//按年龄排序
void sortAscendByAge(Student stu[],int n,point point);
//按姓名排序
void sortAscendByName(Student stu[],int n,point point);
//按成绩排序
void sortAscendByScore(Student stu[],int n,point point);
//打印所有信息
void printAllInformation(Student stu[],int n);
//第二种:===》把重复代码最简化
//给一个函数指针取别名 *后面的就是别名
typedef BOOL (*POINT)(Student stu1,Student stu2);
typedef void (*point)(Student stu[],int n) ;
//声明判断姓名的先后次序的函数
BOOL compareStudentByName(Student stu1,Student stu2);
//声明判断年龄的大小的函数
BOOL compareStudentByAge(Student stu1,Student stu2);
//声明判断成绩的大小的函数
BOOL compareStudentByScore(Student stu1,Student stu2);
//声明一个根据传入的函数指针,选择特定的排序方式的函数
void sortStudent(Student *stu,int n,POINT point);
//第三种:===》函数指针做返回值:在第二种的基础上再简化
//一个函数列表,把字符串和函数名一一对应起来
typedef struct FunctionList{
char name[10];//函数名对应的字符串
POINT p_compare;//函数指针--函数名
}FunctionList;
//声明一个返回函数指针的函数
POINT judgeFunction(char *name,FunctionList *list,int n);
Sort.m
//
// Sort.m
// Lesson_15-8-11
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//
#import "Sort.h"
//第一种=====》
//实现按年龄排序--point为函数指针
void sortAscendByAge(Student stu[],int n,point point){
//中间结构体变量
Student stu_temp={0};
//利用冒泡排序
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
if (stu[j]._age>stu[j+1]._age) {
stu_temp=stu[j];
stu[j]=stu[j+1];
stu[j+1]=stu_temp;
}
}
}
printf("按年龄排序:\n");
//函数回调--操作
point(stu,n);
}
//实现按姓名排序--point函数指针
void sortAscendByName(Student stu[],int n,point point){
//中间结构体变量
Student stu_temp={0};
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
if (strcmp(stu[j]._names, stu[j+1]._names)>0) {
stu_temp=stu[j];
stu[j]=stu[j+1];
stu[j+1]=stu_temp;
}
}
}
printf("按姓名排序:\n");
//函数回调
point(stu,n );
}
//实现按成绩排序--point函数指针
void sortAscendByScore(Student stu[],int n,point point){
//中间结构体变量
Student stu_temp={0};
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
if (stu[j]._score-stu[j+1]._score>0.000001) {
stu_temp=stu[j];
stu[j]=stu[j+1];
stu[j+1]=stu_temp;
}
}
}
printf("按成绩排序:\n");
point(stu,n );
}
//打印所有的信息
void printAllInformation(Student stu[],int n){
for (int i=0; i<n ; i++) {
printf("%s\t\t%c\t\t%d\t%.2f\n",stu[i]._names,stu[i]._sex,stu[i]._age,stu[i]._score);
}
printf("\n");
}
//第二种:===》把上面函数块中的if条件判断用函数指针调用相应的功能--动态调用
//第二种明显比第一种好太多
//实现判断姓名的大小功能
BOOL compareStudentByName(Student stu1,Student stu2){
//实现升序的条件
return strcmp(stu1._names, stu2._names)>0;
}
//实现判断年龄大小的功能
BOOL compareStudentByAge(Student stu1,Student stu2){
return stu1._age-stu2._age>0;
}
//实现判断成绩的大小功能
BOOL compareStudentByScore(Student stu1,Student stu2){
return stu1._score-stu2._score>0.000001;
}
//POINT为函数指针的别名,point为定义的函数指针。
void sortStudent(Student *stu,int n,POINT point){
Student stu_temp={0};
for (int i=0; i<n ; i++) {
for (int j=0; j<n-i-1; j++) {
//函数调用,这里的函数调用,根据maim.m传过来的参数,动态的选择执行某个功能。
if (point(stu[j],stu[j+1])) {
stu_temp=stu[j];
stu[j]=stu[j+1];
stu[j+1]=stu_temp;
}
}
}
//调用打印信息的函数
printAllInformation(stu, n);
}
//第三种:===》函数指针做返回值
//根据用户输入的字符串返回相应的函数名(函数指针)
//并且,返回的函数名是之前定义好的结构体成员变量--也就是函数名
POINT judgeFunction(char *name,FunctionList *list,int n){
POINT point_name=NULL;
for (int i=0; i<n ; i++) {
if (strcmp(name, list[i].name)==0) {
point_name=list[i].p_compare;
}
}
//返回函数指针--也就是结构体数组中对应的函数名
return point_name;
}