1. 回调函数是什么?
2. qsort使⽤举例
一、回调函数是什么?
简单来说回调函数就是一个通过函数指针调用的函数
我们来举一个的例子来对比两者的区别。
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 num1 = 0;
int num2 = 0;
int input = 0;
do
{
printf("***1.add 2 sub********\n");
printf("***3.mul 4.div********\n");
printf("***********************\n");
printf("***********************\n");
scanf("%d", &input);
switch (input)
{
int ret = 0;
case 1:
printf("请输入两个数字\n");
scanf("%d%d", &num1, &num2);
ret = add(num1, num2);
printf("%d\n", ret);
break;
case 2:
printf("请输入两个数字");
scanf("%d%d", &num1, &num2);
ret = sub(num1, num2);
printf("%d\n", ret);
break;
case 3:
printf("请输入两个数字");
scanf("%d%d", &num1, &num2);
ret = mul(num1, num2);
printf("%d\n", ret);
break;
case 4:
printf("请输入两个数字");
scanf("%d%d", &num1, &num2);
ret = div(num1, num2);
printf("%d\n", ret);
break;
case 0 :
printf("结束计算");
break;
}
} while (input);
return 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 ;
}
// 用函数指针来接收函数,然后通过函数名来接收
//其函数的本质还是 返回类型 数字名(形参),这里的形参是一个函数指针,用来储存函数指针
void dig(int(*pr)(int , int)) //函数指针 是用来接收函数的地址的,函 数指针接收什么类型的函数地址
{ //就调用什么类型的函数
int ret = 0;
int x, y;
printf("请输入操作数\n");
scanf("%d%d", &x, &y);
ret = pr (x, y); // pr里边储存的是函数的地址,这里拿到的是函数地址,通过地址找到函数然后进行使用。
printf("ret =%d\n", ret);
}
int main()
{
int num1 = 0;
int num2 = 0;
int input = 0;
do
{
printf("***1.add 2 sub********\n");
printf("***3.mul 4.div********\n");
printf("***********************\n");
printf("***********************\n");
printf("请选择你要进行的算法\n");
scanf("%d", &input);
switch (input)
{
case 1 : //我们通过数字1 2 3 4 到 + - * /;
dig(add);
break;
case 2:
dig(sub);
break;
case 3:
dig(mul);
break;
case 4:
dig(div);
break;
case 0 :
printf("程序结束");
break;
default :
printf("选择错误,请重新选择");
break;
}
} while (input);
return 0;
}
通过该代码我们可以发现代码变得更加简洁的,上一章我们还使用了函数指针数组,大家对比一下代码,看看自己能够更适合那种。
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。
我们可以把调⽤的函数的地址以参数的形式传递过去,使⽤函数指针接收,函数指针指向什么函数就调⽤什么函数,这⾥其实使⽤的就是回调函数的功能。
二、qsort 使用举例
#include<stdlib.h>
//我们在使用qsort 排序的时候需要自己来写一个函数,如下:
int sort(const void * pr1, const void * pr2) //这里我们排序不仅仅是排序的整数,还可以排序的是其它类型的,所以我们先用void *来接收数据
{
{
return (*(int*)pr1 - *(int*)pr2); //这里我们进行强制类型转换的原因我是因为我们要排序肯定提前已经知道了所排序的类型,这里是整形数组我们就可以把其转换为int*类型
//这里我们来解读一下,pr1拿到的是空指针要使用的话我们先将其转换为int*类型的指针才能进行使用
// 转化为int*类型之后我们就可以通过*操作符拿到其对应的数,然后比较(pr2同理)
}
//该函数会自动比较数组中每个相邻元素的值,并返回一个整数
}
int main()
{
int arr[10] = { 3,1,5,7,4,2,6,0,8,9 };
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), sort); //使用该函数要包含一个头文件
//通过该函数我们就可以把一组无序类型的数组排序为有序的数组,具体的排序编译器的库已经会帮我们实现
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", *(arr + i));
}
return 0;
}
我们再来举一个例子
使⽤qsort排序结构数据
struct s
{
char name[10];
int age[5];
};
int age_sort(const void* er1, const void* er2)
{
return (((struct s*)er1)->age - ((struct s*)er2)->age);
//这里我们指向的是结构体中的age,然后进行比。
}
void text2()
{
struct s arr[] = { {"ik",50},{"wkh",20},{"zj",32} };
int ret = sizeof(arr) / sizeof(arr[0]);// 数组中元素的个数
int si = sizeof(struct s); //一个元素的字节
qsort(arr, ret, si, age_sort);
}
//这里我们比较的是结构体中name元素的大小
int name_sort(const void* pr1, const void *pr2)//排序年龄
{
// strcmp是用来比较字符串的的长度,需要包含头文件
return strcmp (((struct s *)pr1)->name , ((struct s*)pr2)->name); //这里我们通过该方式也可以拿到地址对应的数组
//这种方式我们可以更清楚的看出所比较的是结构体中的那种元素
}
void text1()
{
struct s arr[] = { {"ik",50},{"wkh",20},{"zj",32} };
int ret = sizeof(arr) / sizeof(arr[0]);// 数组中元素的个数
int si = sizeof(struct s); //一个元素的字节
qsort(arr, ret, si, name_sort);
}
int main()
{
text1();
printf("\n");
text2();
return 0;
}
相信通过这两个例子大家就可以很好的掌握了关于qsort 函数的使用