C语言指针(4)
1. 回调函数
回调函数就是通过一个函数指针调用的函数。
下面是实现的一个简单的计算器:
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y, input, ret;
do {
printf("*************************************\n");
printf(" 1.add 2.sub \n");
printf(" 3.mul 4.div \n");
printf(" 0.exit \n");
printf("*************************************\n");
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入操作数:>");
scanf("%d%d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 2:
printf("请输入操作数:>");
scanf("%d%d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 3:
printf("请输入操作数:>");
scanf("%d%d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 4:
printf("请输入操作数:>");
scanf("%d%d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 0:
printf("程序退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
我们可以发现在上面代码中switch
函数中有非常多的冗余,但是里面又有使用了不同函数的地方,这里该怎么简化。
我们可以发现虽然它们函数不同,但是函数的返回值和形参是一样的,那么这里我们就可以使用回调函数。
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
void calc(int(*p)(int, int))
{
int ret, x, y;
printf("请输入操作数:>");
scanf("%d%d", &x, &y);
ret = p(x, y);
printf("ret = %d\n", ret);
}
int main()
{
int input;
do {
printf("*************************************\n");
printf(" 1.add 2.sub \n");
printf(" 3.mul 4.div \n");
printf(" 0.exit \n");
printf("*************************************\n");
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(sub);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("程序退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
我们将冗余部分写成一个函数,再将需要调用的函数的函数指针传给该函数即可,这样就简化了我们的代码。
2. qsort
qsort
函数是C语言库函数中的一个用于排序数组的函数,使用这个函数需要包含stdlib.h
头文件。
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
使用qsort
函数需要传递四个参数:
base
:指向待排序数组的指针,可以不指向第一个元素,指向第几个元素就从第几个元素开始排序。num
:从base指针开始,需要排序的元素的个数。size
:每个元素所占用的字节数。compar
:一个比较函数的函数指针,这个比较函数决定了排序规则。
关于compar:
- 形参必须为两个
const void*
指针,这两个指针分别指向两个元素 - 返回值必须为整数
- 返回值<0:第一个
const void*
指向的元素将排在前面 - 返回值=0:两个
const void*
指向的元素视为等效 - 返回值>0:第一个
const void*
指向的元素将排在后面
- 返回值<0:第一个
举例:
int cmp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
上面的比较函数意思是,对于两个int
类型的元素,希望如果p1
指向的元素小于p2
指向的元素时(此时返回负值)p1
指向的元素排在p2
指向的元素前面,那么传入qsort
后的结果就是,该比较规则排序出来的数组是升序的(从小到大)。
实际应用:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
int main()
{
int arr[] = { 5,6,9,8,2,10,3,1,4,7 };
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
printf("%d ", arr[i]);
return 0;
}
3. sizeof和strlen的对比
3.1 sizeof
在之前我们就使用过sizeof
,sizeof
是用于计算变量所占用的内存空间大小的,单位是字节,如果操作数是类型的话,计算的就是对应类型创建变量所占用内存空间的大小。
sizeof
只关注占用内存空间的大小,不在乎内存中存放的是什么数据。
3.2 strlen
strlen
是C语言的库函数,需要包含头文件string.h
,功能是求字符串的长度,函数原型如下:
size_t strlen(const char* str);
统计的是从str
地址开始计算,到\0
之前字符串中字符的个数。
strlen
函数会一直向后找\0
字符,直到找到为止,可能存在越界查找。
3.3 sizeof和strlen的对比
sizeof | strlen |
---|---|
sizeof 是操作符 | strlen 是库函数,需要包含头文件string.h |
sizeof 计算操作数所占内存的大小,单位是字节 | strlen 是求字符串长度,统计的是\0 之前字符的个数 |
不关注内存中存放的数据 | 关注内存中知否有\0 ,如果没有就会继续往后就算,可能会越界 |