微信网站开发费用,品牌故事,想学动漫制作可以上什么学校,亚洲一线产区二线产区精华目录
一、函数指针数组
1.1函数指针数组写法 1.2函数指针用途
二、指向函数指针数组的指针
2.1概念 三、回调函数 3.1用法
3.2qsort排序
总结
前言
我们接着上一篇的函数指针往下学习。 一、函数指针数组
1.1函数指针数组写法
我们都知道指针数组#xff0c;里面可以…目录
一、函数指针数组
1.1函数指针数组写法 1.2函数指针用途
二、指向函数指针数组的指针
2.1概念 三、回调函数 3.1用法
3.2qsort排序
总结
前言
我们接着上一篇的函数指针往下学习。 一、函数指针数组
1.1函数指针数组写法
我们都知道指针数组里面可以放字符指针或者整形指针例如
char* arr[6];//字符指针数组int* arr[6];//整形指针数组
那么我们就可以想一想函数指针数组是否可以呢 当然可以写函数指针数组需要在函数指针这个基础上进行改造
int(*str)(const char*) my_strlen;int(*str[5])(const char*);
第一行 是一个函数指针我们将my_strlen这个函数的地址赋予给它当我们想要把前面的函数指针改成函数指针就可以在里面加上数组元素个数其实就是在这个函数指针后面加上一个方括号再确定元素个数就可以了。
int(*)(const char*); 我们去掉数组名和元素剩下的就是一个函数指针所以就是这个数组里面存放的就是这个函数的地址。我们就可以赋值传入地址
int(*str[5])(const char*){ my_strlen,.....} 1.2函数指针用途
我们可以用一个简单的可以实现整数加减乘除的计算器。
先实现一个简单的菜单和基本逻辑的实现重点实际是函数的编写和函数的调用VS2022
#define _CRT_SECURE_NO_WARNINGS 1
#includestdio.h
void menu()
{printf(********************************************\n);printf(*********** 1.add 2.sub ***********\n);printf(*********** ***********\n);printf(*********** 3.mul 4.div ***********\n);printf(*********** 0.exit ***********\n);printf(********************************************\n);}int main()
{int input 0;do{menu();printf(请选择);scanf(%d, input);switch (input){case 1:break;case 2:break;case 3:break;case 4:break;case 0:printf(退出计算器\n);break;default:printf(选择错误\n);} } while (input);return 0;
}
这里规定的是选择1,2,3,4,0分别执行加减乘除和退出。在这里实现每一个模块的功能
int Add(int x, int y)
{return x y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}
接下来实现调用
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d, input);switch (input){case 1:printf(请输入两个数:);scanf(%d %d, x, y);retAdd(x, y);printf(结果是 %d\n, ret);break;case 2:printf(请输入两个数:);scanf(%d %d, x, y);ret Sub(x, y);printf(结果是 %d\n, ret);break;case 3:printf(请输入两个数:);scanf(%d %d, x, y);ret Mul(x, y);printf(结果是 %d\n, ret);break;case 4:printf(请输入两个数:);scanf(%d %d, x, y);ret Div(x, y);printf(结果是 %d\n, ret);break;case 0:printf(退出计算器\n);break;default:printf(选择错误\n);} } while (input);return 0;
}
这样一个简单的计算器就写好了我们可以运行并且测试。但这只是这几种简单的运算当我们如果想要拓展其它的算数方法那么函数要写switch里面的case也要写那么里面就会变得非常长这时候我们就可以优化一下。
我们知道函数的调用参数和返回值都一样所以可以写上函数指针数组存放函数的地址这种叫做转移表
int (*pf[5])(int,int) { NULL,Add,Sub,Mul,Div };
我们这里用上一个名字为pf的函数指针数组来接受这些函数的地址每一个函数对应的下标就是菜单上规定的数字。
这时候我们就不需要用switch语句了我们想要选择几就访问下标为几的位置。这时候我们改一下主函数
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d, input);if (input 0){printf(退出计算器\n);break;}else if (input 1 input 4){printf(请输入两个数:);scanf(%d %d, x, y);ret pf[input](x, y);printf(结果是 %d\n, ret);}else{printf(选择错误\n);}} while (input);return 0;
}
这样未来我们想要添加功能就只需要加上新函数的编写剩下的只需要改一改限制条件就可以其他都不用改动大大改善了switch的代码量。但这个上述代码只适用两个整数之间的操作双目操作符的运算。
函数指针数组在动态调用函数、简化代码逻辑、扩展性和灵活性以及实现回调函数等方面具有很高的实用价值是一种常用的编程技术。 二、指向函数指针数组的指针
2.1概念 int(*pf[5])(int,int);
ppfpf; 如上述代码pf是一个存放函数指针的一个五个元素的数组而ppf指向这个数组所以就是指向函数指针数组的指针。
int(*(*ppf)[5])(int,int);
int(*)(int,int);
(*ppf)代表是一个指针(*ppf)[5]代表指向的是一个五个元素的数组而int(*)(int,int)代表是一个函数指针所以数组里存放的是函数指针这个数组也就是一个函数指针数组所以ppf就是一个指向函数指针数组的指针;
三、回调函数 回调函数就是一个通过函数指针调用的函数如果把函数的指针地址作为一个参数传给另一个函数当这个指针被用来调用其所指向的函数时我们就说这是回调函数回调函数b不是由该函数的实现方法直接调用而是在特定的事件或条件发生由另外一方调用的对于该事件或条件进行影响。 也就是用函数指针调用函数。
3.1用法
之前的switch,,,case语句是这样的 case 1:printf(请输入两个数:);scanf(%d %d, x, y);retAdd(x, y);printf(结果是 %d\n, ret);break;case 2:printf(请输入两个数:);scanf(%d %d, x, y);ret Sub(x, y);printf(结果是 %d\n, ret);break;
我们可以看到很多都是一样的代码那可不可以把一样的代码放在一个函数里面调用呢
void func()
{printf(请输入两个数:);scanf(%d %d, x, y);retAdd(x, y);printf(结果是 %d\n, ret);
}case 1:func();break;
case 2:func();break;
这里就有一个问题这里两次case都是计算加法这时候我们就可以当我们case 1 的时候将加法的地址传到函数中当case 2 的时候把减法的地址传过去
void func(int(*p)(int,int))
{printf(请输入两个数:);scanf(%d %d, x, y);retp(x, y);printf(结果是 %d\n, ret);
}case 1:func(Add);break;
case 2:func(Sub);break;
把函数的参数写成一个函数指针就可以调用的时候就用指针名和传参就可以实现了。这里通过p来调用这些函数就叫做回调函数。
qsort函数就是一个典型的例子。
3.2qsort排序
这里先介绍一下这个函数
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
这里传入的参数分别是是要排序的目标起始位置排序的个数单个的大小还有比较函数。这里的比较函数是需要自己进行编写的并且比较函数是返回的一个数。
int compareMyType (const void * a, const void * b)
{if ( *(MyType*)a *(MyType*)b ) return -1;if ( *(MyType*)a *(MyType*)b ) return 0;if ( *(MyType*)a *(MyType*)b ) return 1;
} 这里是官方给出的代码实际我们只需要返回一个值就可以。
下面是通过qsort函数来排序整数数组还有排序结构体
给定一个整数数组进行排序
//基于快速排序的stdlib库里的qsort进行排序#includestdio.h
#includestdlib.hint comper(const void*e1, const void*e2)
{return *(int*)e1 - *(int*)e2;
}int main()
{int arr[5] { 4,6,2,3,1 };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), comper);for (int i 0; i sz; i){printf(%d , arr[i]);}return 0;
}
基于结构体按照年龄和名字来进行排序
//结构体排序
#includestdio.h
#includestring.h
#includestdlib.h
struct Stu
{char name[20];int age;
};
//年龄排序
int comper(const void* e1, const void* e2)
{return ((struct Stu*)e1)-age - ((struct Stu*)e2)-age;
}//按照名字来排序
int comper1(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)-name , ((struct Stu*)e2)-name) ;//按照字典序进行排序
}void test2()
{struct Stu s[3] { {zhangsan,30},{lisi,50},{wanghu,33} };int sz sizeof(s) / sizeof(s[0]);qsort(s,sz,sizeof(s[0]),comper1);for (int i 0; i sz; i){printf(%s %d\n, s[i].name, s[i].age);}
}int main()
{test2();return 0;
} 总结
这里进行了函数指针数组的用法和写法回调函数sqsort等的知识