// 函数指针???
void fun1();
void fun1()
{
// 定义:函数指针是指针,是指向函数的指针
// 函数名称和数组名称一样,都是代表首地址
printf("fun1 = %p\n", fun1);
// 注意:函数被编译完成后被存放在内存中的代码区
// 函数指针的写法:
// 1. 赋值函数声明
// 2. 去除函数名,换成一对'()',里面加上'*',再加变量名
// 3. 赋初始为NULL
// 1. void fun1()
// 2. void (*p)()
// 3. void (*p)() = NULL;
void (*p)() = NULL;
// 函数指针定义,p是变量,其它是类型(通常没有形参a,b)
// 给函数指针赋值函数名
p = fun1;
// 函数指针当函数名使用
p(); // 调用函数,使用指针来调用
}
// 练习1
void printHello();
void printHello()
{
printf("Hello\n");
}
void practice1();
void practice1()
{
// 定义一个可以指向上述函数的函数指针,并通过函数指针实现调用该函数
// 1. 函数指针类型
void (*hello)() = NULL; // 创建函数指针变量
hello = printHello; // 给函数指针赋值
hello(); // 使用指针,调用函数
}
// 练习2
// 求和函数
int sum(int a, int b);
int sum(int a, int b)
{
return a + b;
}
// 求最大值
int maxValue(int a, int b);
int maxValue(int a, int b)
{
return a > b ? a : b;
}
void practice2();
void practice2()
{
// 定义两个函数,一个求最大值,一个求和,输入maxValue或sum分别求3,5的最大值或和(提示,定义一个函数指针,根据输入内容指向不同函数,最后一次调用完成)
// 定义函数指针
int a = 0, b = 0, result = 0, choose = 0;
int (*p) (int, int) = NULL;
printf("请输入第一个数:");
scanf("%d", &a);
printf("请输入第二个数:");
scanf("%d", &b);
printf("~~~~~~~~~~\n");
printf("1. 求和\n");
printf("2. 求最大值\n");
printf("~~~~~~~~~~\n");
printf("请选择:");
scanf("%d", &choose);
switch (choose) {
case 1: {
p = sum;
break;
}
case 2: {
p = maxValue;
break;
}
default: {
printf("输入错误(默认求和)\n");
p = sum;
break;
}
}
// 使用指针进行函数的调用
result = p(a, b);
printf("result = %d\n", result);
}
// 函数回调(函数指针作为参数)
// 返回值:int类型
// 函数名:getValue
// 参数列表:1.a(int类型) 2.b(int类型) 3.p (int(*)(int, int)类型,函数指针)
int getValue(int a, int b, int (*p)(int, int));
int getValue(int a, int b, int (*p)(int, int))
{
// 使用函数指针去调用函数,此时,执行的时候到底调用哪个函数还不知道,看你传进来的函数指针指向的是哪个函数
return p(a, b);
}
// 练习3
// 写一函数查找成绩90分以上的学员,使用回调函数在姓名后加”高富帅”
typedef struct {
char name[30]; // 姓名
int age; // 年龄
float score; // 分数
} Student;
// 打印所有学生的函数
void printStudents(Student *stus, int count);
void printStudents(Student *stus, int count)
{
for (int i = 0; i < count; i++) {
printf("name = %-15s age = %-4d score = %-5.2f\n", (stus + i)->name, (stus + i)->age, (stus + i)->score);
}
}
// 修改学生姓名函数
void changeStudentName(Student *stu);
void changeStudentName(Student *stu)
{
strcat(stu->name, "~高富帅");
}
// 函数两个参数:
// 1. 学生数组
// 2. 修改姓名的函数指针
void practice3(Student *stus, int count, void(*p)(Student *stu));
void practice3(Student *stus, int count, void(*p)(Student *stu))
{
for (int i = 0; i < count; i++) {
// 判断当前学生分数是否大于90分
if ((stus + i)->score >= 90) {
// 使用指针调用函数
p((stus + i));
}
}
}
// 动态排序
// 为函数指针起别名
typedef BOOL(*PFUN)(Student *stu1, Student *stu2);
// 按姓名排序
BOOL sortByName(Student *stu1, Student *stu2);
BOOL sortByName(Student *stu1, Student *stu2)
{
if (strcmp(stu1->name, stu2->name) > 0) {
return YES;
}
return NO;
}
// 按年龄排序
BOOL sortByAge(Student *stu1, Student *stu2);
BOOL sortByAge(Student *stu1, Student *stu2)
{
if (stu1->age > stu2->age) {
return YES;
}
return NO;
}
// 按分数排序
BOOL sortByScore(Student *stu1, Student *stu2);
BOOL sortByScore(Student *stu1, Student *stu2)
{
if (stu1->score > stu2->score) {
return YES;
}
return NO;
}
// 动态排序,排序函数
void sortStudents(Student *stus,int count, PFUN p);
void sortStudents(Student *stus,int count, PFUN p)
{
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - 1 - i; j++) {
// if中的条件取决于函数指针指向的函数
if (p(stus + j , stus + j + 1)) {
Student tempStu = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = tempStu;
}
}
}
}
// 函数返回值是函数指针
int min(int a, int b);
int min(int a, int b)
{
return a > b ? b : a;
}
int max(int a, int b);
int max(int a, int b)
{
return a > b ? a : b;
}
// 给函数指针起个别名
typedef int (*PFUN2) (int, int);
// 结构体指针与其对应的字符串
typedef struct {
char name[30]; // 函数名字符串形式
PFUN2 function; // 函数指针
} NameFunctionPair;
PFUN2 getFunctionByName(char *name);
PFUN2 getFunctionByName(char *name)
{
if (strcmp(name, "min") == 0) {
return min;
} else if (strcmp(name, "max") == 0) {
return max;
}
return NULL;
}
int main(int argc, const char * argv[])
{
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数指针作为参数的调用
int (*p)(int, int) = NULL;
p = sum;
// p = maxValue;
// 调用getValue函数的时候,具体是返回和还是最大值取决于函数指针p的指向的函数
int result = getValue(10, 20, p);
// printf("result = %d\n", result);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 练习3
Student stus[] = {
{"张赛赛", 18, 89.9},
{"王赛赛", 12, 29.1},
{"李赛赛", 41, 100.0},
{"赵赛赛", 89, 96.9}
};
// 指向修改学生姓名函数的指针
void (*p2)(Student *) = changeStudentName;
// 数组元素个数
int stusCount = sizeof(stus) / sizeof(Student);
// 修改之前打印
printf("\n修改之前:\n");
printStudents(stus, stusCount);
// 修改
practice3(stus, stusCount, p2);
// 修改之后打印
printf("\n修改之后:\n");
printStudents(stus, stusCount);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
printf("\n\n\n");
// 动态排序
Student students[] = {
{"xiaohong", 19, 90.5},
{"xiaolv", 25, 100.0},
{"xiaolan", 14, 23.5},
{"xiaobai", 26, 10.0},
{"xiaoqing", 12, 56.4}
};
// 数组长度
int studentsCount = sizeof(students) / sizeof(Student);
// 排序之前
printf("\n排序之前:\n");
printStudents(students, studentsCount);
// 函数指针,负责制定排序方式
PFUN p3 = NULL;
p3 = sortByAge; // 根据年龄排序
p3 = sortByName; // 根据姓名排序
p3 = sortByScore; // 根据分数排序
// 排序
sortStudents(students, studentsCount, p3);
// 排序之后
printf("\n排序之后:\n");
printStudents(students, studentsCount);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 数据结构
NameFunctionPair nameFunctionPair[] = {
{"min", min},
{"max", max}
};
// 根据字符串去获取函数名称
PFUN2 fun = NULL;
fun = getFunctionByName(nameFunctionPair[0].name);
// 使用指针调用返回的函数
int result2 = fun(100, 30);
printf("\nresult2 = %d\n", result2);
return 0;
}