指针的深入了解6

1.回调函数

回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数
时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。我们在上一讲的calc函数就是回调函数,因为我们在计算器的模拟实现中有些代码时重复的,所以我们将其包装成一个函数,让其每次使用时进行调用。

2.qsort排序

我们在之前学过冒泡排序,但是我们的冒泡排序只能排序整型数据,而这个qsort可以排序任意函数。

1.qsort的参数

有四个参数,第一个参数是指向需要排序的指针也就是数组的首元素地址,第二个参数是需要排序元素的个数,第三个参数是每个元素的大小,最有一个参数是我们给定一个排序方式,且这个排序方式的返回值为大于0、小于0,或等于0.

 2.qsort头文件

qsort的头文件为

3.qsort排序演示

#include
#include
int sort(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}
 void print(int* pt, int num)
{
	 for (int i = 0; i < num; i++)
	 {
		 printf("%d ", pt[i]);
	 }
	 printf("\n");
}
int main()
{
	int arr[5] = { 5,3,4,1,2 };
	size_t num = sizeof(arr) / sizeof(arr[0]);
	print(arr, num);
	qsort(arr, num, sizeof(arr[0]), sort);
	print(arr,num);
	return 0;
}

我们的sort函数就是我们给定的排序规则,void*的指针不能直接解引用,所以我们将其强制类型转换为int* 这样我们就可以找到数组的元素了,p1>p2返回大于0的值,p1=p2返回0,p1

我们来看看结果:

指针的深入了解6_第1张图片

这个地方我们是以升序排序的,那怎么降序排序呢?其实只要在我们给定的规则上改动即可,我们的sort函数的指针位置调换即可。

指针的深入了解6_第2张图片

我们再次运行试试看:

指针的深入了解6_第3张图片

 因为qsort库函数的参数是viod*的指针,所以我们可以传任意指针。那么如果我们想排序结构体是否可以用qsort排序呢?

4.qosrt排序结构体

在这之前我们先来学习一个库函数strcmp,他是用来专门比较字符串的,比较规则是字符所对应的ASCLL码值进行比较的。

它有两个参数都是char*,所以我们只需要给它喜欢传参即可,这个指针也就指向要比较字符串的指针,一般为我们用其数组名。const作为它的参数的原因是为了增加代码的安全性,我们只是为了比较,并不想改变字符串的内容,所以我们加上const,这样我们如果写错了要改变字符串的内容,编译器就会报错。它的头文件为

它的返回值也刚刚好满足qsort的第四参数的规则。

 演示如下:

struct Stu
{
	char name[15];
	int age;
};
int sort(const void* p1, const void* p2)
{
	return strcmp( (char*) p1,  (char*) p2);
}
void print(struct Stu *pt,size_t num)
{
	for (int i = 0; i < num; i++)
	{
		printf("%s %d ", pt->name, pt->age);
		pt++;
	}
	printf("\n");
 }

int main()
{
	struct Stu s[] = { {"zhang",13},{"chen",19},{"qing",17} };
	size_t num = sizeof(s) / sizeof(s[0]);
	print(&s, num);
	qsort(s, num, sizeof(s[0]), sort);
	print(&s,num);
	return 0;
}

结构体指针是不需要解引用的,直接->就可以找到对应成员。我们为了好观察排序前排序后都进行打印。

结果如下:

指针的深入了解6_第4张图片

 我们可以看到确实是按照ASCLL码值的大小来排序的,z的ASCLL码值大于c、q的ASCLL码值。

我们可以思考下怎样将冒泡排序进行改进,让其能够排序任意类型的数据。

指针的深入了解6_第5张图片 谢谢

你可能感兴趣的:(c语言,开发语言)