我的上篇博客介绍了函数指针和函数指针数组,最后还留下了疑问:如果用字符+ - * /来完成计算器,会怎样。当然只能乖乖的switch写重复的几段。如果想回顾:写文章-CSDN创作中心
(本节需要提前掌握函数指针。)
我们将代码写出来是
这里有个细节,取字符的时候后面加一个%*c过滤我们的回车'\n'或者最后加个getchar()也可。
那是否可以将这重复的三段写成函数呢?那就要用到我们的回调函数:将我们的函数地址传给回调函数,让它运行其他代码和调过来的函数。这里需要用到函数指针:
封装好的函数:
主函数就变成了:
是不是简洁很多,不用频繁的复制粘贴。
那么接下来乘热打铁,我们用回调函数来升级一下我们的冒泡排序,让它可以排序所有类型数据:
首先我们看看改变后冒泡的输入值变化:首先是带排数组没变,数组个数没变,多了一个wide表示每个数据的大小(这个在后面我特别说一下),多了一个函数指针,这个传入的函数我们要自己写,让我们自己实现两个变量的大小判断
这里p里面的一长串表达式我们分析一下。因为void*是不能解引用的,他没有类型解引用不知道访问几个字节,所以要人为的强制转换。因为结构体类型内存不确定,所以只能以char这个只有一字节的类型作为媒介。我们以y=0这个情况为例,左边的表达式就是数组的起始地址,右边刚好跳过了一个数据的内存长度。这里也体现了wide这个变量的重要性。
再看主体,和普通冒泡不同的就是判断部分。
判断函数由我们自己写。一般是返回前面的数据后面的数据的值,如果大于0就交换。如果我们把返回值前面加个负号那么就不是从小到大排序了,是从大到小排序。
我举出两个例子,分别是整型数组和结构体
这里需要自己强制性转换一下类型,让它们能访问正确的内存大小。结构体的指针要提前强制性转换,再用一个结构体指针接收一下,不然不能用"->"
为什么回调函数要我们自己写呢,因为这个部分无被普通函数通过代码来解决 所有条件下的问题。意思就是不具有泛用性。
接下来是swap函数:这个函数为何又是固定的char类型呢?我们看下面的for循环就是将
前后两个指针内存一字节一字节的交换。char又刚好是一字节,所以用char合适。wide是数据的单个的大小,假如是7bity,那么就交换7次。
那么经过我们一写后,我们可以自己总结一下回调函数的作用。我们写几行代码发现这几行是重复的。我们会进行函数封装,但是唯一变化的就是有部分函数不同。那么就可以用回调函数将这部分包含住,使得原来的几行代码能够顺利的封装,将小部分的不可统一的代码交给回调函数处理。