C语言:简单理解指针(5)
简单理解指针
1.回调函数
回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的实践或条件发生时由另外一方调用的,用于对该事件或条件进行相应。
#include
int add(int x, int y)
{
return x + y;
}
int mul(int x, int y)
{
return x * y;
}
int sub(int x, int y)
{
return x - y;
}
int div(int x, int y)
{
return x / y;
}
void calc(int(*pf)(int, int))
{
int ret = 0;
int x, y;
printf("输入操作数:");
scanf("%d%d",&x,&y);
ret = pf(x, y);
printf("%d
", ret);
}
int main()
{
int input = 1;
do
{
printf("**1.add 2.mul**
");
printf("**3.sub 4.div**
");
printf("**0.exit
");
printf("
");
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(mul);
break;
case 3:
calc(sub);
break;
case 4:
calc(div);
break;
case 0:
printf("退出成功!
");
break;
}
} while (input);
return 0;
}

2.qsort 函数
qsort 函数在C语言中时专门用来做数据排序的:
这个函数对数据的排序采用的是快速排序的思想
这个函数可以用来排序任意类型的数据
qsort函数原型:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *));
- base: 待排序数组的首地址 用 void* 实现通用型,可接收任意类型数组的地址
- nitems: 数组中元素的个数 size_t 是无符号整数类型(对应 unsigned int),表示数量
- size :数组中单个元素的字节大小 如 int 传 sizeof(int),结构体传 sizeof(结构体名),由编译器计算,保证类型适配
- compar :int (*)(const void *, const void *) 比较回调函数的指针 核心通用逻辑:排序规则由用户自定义的该回调函数决定,qsort 内部会反复调用此函数比较两个元素
- 形参:const void* a、const void* b → 指向待比较的两个元素,const 保证元素不被意外修改,void* 适配任意类型
返回值:int → 由返回值的正负 / 零决定两个元素的排序顺序,规则固定:
返回 负数:a 排在 b 前面(a < b)
返回 0:a 和 b 相等,顺序不变
返回 正数:a 排在 b 后面(a > b)
#include
//qsort函数要先实现一个比较函数来决定排列方式
int cmp(const void*p1,const void*p2)
{
return(*(int*)p1 - *(int*)p2);
}
int main()
{
int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
int i = 0;
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp);
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}

3.qsort函数的模拟实现
#include
int cmp(const void* p1, const void* p2)//程序员1
{
int num1 = *(int*)p1;
int num2 = *(int*)p2;
return num1 - num2;
}
void swap(const void* p1, const void* p2,int n)//程序员1
{
int i = 0;
for (i = 0; i < n; i++)
{
char tmp = *((char*)p1+i);
*((char*)p1+i) = *((char*)p2+i);
*((char*)p2+i) = tmp;
}
}
void my_qsort(void* base, int n, int type, int(*cmp)(const void*, const void*))//程序员1
{
int i = 0;
int j = 0;
for (i = 0; i < n - 1; i++)//比较的趟数
{
for (j = 0; j < n - i - 1; j++)//一趟比较的次数
{
if (cmp((char*)base + j * type, (char*)base + (j+1) * type) > 0)
{
swap((char*)base + j * type, (char*)base + (j+1) * type , type);
}
}
}
}
int main()//调用者,程序员2
{
int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
int i = 0;
my_qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp);
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}

如上就是qsort函数模拟实现,这里为大家解答几个疑惑,为什么要将调用函数中的变量强制转化为char*,这是因为我们在实现这个函数并调用时,并不知道参数类型,可能是字符型,也可能是整形,所以这时候就要一个一个字节地交换。









