深入解剖指针(4)

个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客

目录

回调函数

qsort使用举例

使用qsort函数排序整型数据 

使用qsort排序结构数据 

qsort函数的模拟实现 


 

回调函数

回调函数就是一个通过函数指针调用的函数。 如果你把函数指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

简单来说就是:当我拥有一个函数(地址)指针时,在一些特定的情况下,通过函数指针回过头来调用这个函数,那么这个被调用的函数就是回调函数。

简易计算器的制作(函数指针数组的实践)-CSDN博客这篇文章中写的计算代码,就是可以用这个回调函数的例子。如果我们要使用加法计算两个数的值,不是直接由main函调用的,而是由calc函数来调用对应的加法函数。这便是回调函数。

qsort使用举例

使用qsort函数排序整型数据 

如果我们想要排序一组数据,按照升序或者降序的方式,首先想到的就是冒泡排序。这个排序在深入解剖指针篇(2)-CSDN博客 这篇文章中介绍了。核心思想就是:两两相邻元素的比较。

我们现在就用qsort函数来实现。首先,就得了解什么是qsort函数。

上面就是关于qsort函数的基本介绍。

void qsort(void* base, //这个base就是要排序的元素的起始地址
		   size_t num, //这个num就是要排序的元素个数
		   size_t size,//这个size就是要排序的元素对应字节数
		   int (*compar)(const void*, const void*));//这个其实就是一个 有比较功能函数 的指针

上面那个比较功能就是你要怎么实现这个排序,就用什么功能。例如:我要实现升序功能,那么这个函数就是实现升序的功能。 

我们现在就可以开始模拟实现冒泡排序了。

#include <stdio.h>
#include <stdlib.h>//qsort函数所需的头文件

//打印数据看看是否排序成功
void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

//调用的排序函数
//由于创造这个函数的人,不知道我们会比较什么样的数据,因此,就要void*来接收。
int int_cmp(const void* p1, const void* p2)
{
    //qsort默认的是升序,由于void*不能直接解引用,所以就先得强制转换为要比较(int*)的数据类型
	return (*(int*)p1 - *(int*)p2);//如果我们像排成降序,就可以把这个给反过来
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), int_cmp);
	Print(arr, sz);
	return 0;
}

可以看出来这个qsort函数排序是正确的。

使用qsort排序结构数据 

我们假设要排序一些不是整型的数据,那么冒泡排序肯定是不行的。但是我们可以采用其思想,来进行排序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu//创建一个结构体类型:学生
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}

void Print(struct stu* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", (p+i)->name);//结构体指针->成员名
	}
	printf("\n");
}
int main()
{
    //创建一个结构体数组并且初始化
	struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
	Print(arr, sz);
	return 0;
}

 strcmp是用来比较字符串大小的,具体用法请看:字符函数与字符串函数(上)-CSDN博客 

通过上面的学习,我们就可以发现这个qsort函数在使用时,需要我们根据自己的需求来写出对应的比较函数。

结构体成员的间接访问 

我们在访问结构体成员时,有两种操作符,一种是 . (直接访问),还有一种是 ->(间接访问)。

直接访问在操作符详解(下)-CSDN博客 里讲过。

结构体指针->成员名 ,即当 -> 的左边满足时结构体指针时,我们要访问结构体成员就可以用->。 

上面是排序其名字,我们还可以排序其年龄

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return (((struct stu*)e1)->age - ((struct stu*)e2)->age);
}

void Print(struct stu* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", (p + i)->age);
	}
	printf("\n");
}

int main()
{
	struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
	Print(arr, sz);
	return 0;
}

qsort函数的模拟实现 

我们现在就来通过模拟实现qsort函数(用冒泡的方式)来排序整形数组。

#include <stdio.h>
int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

//因为前面有强制转换为char*了,所以我们也就不用void*了
void Swap(char* p1, char* p2, size_t width)
{
	//如果是排序char的数据,我们就只能一个字节一个字节的交换
	for (int i = 0; i < width; i++)
	{
		char tmp = *(p1+i);
		*(p1+i) = *(p2+i);
		*(p2+i) = tmp;
	}
}

void bubble_sort(void* base, size_t num, size_t width, int(*cmp)(void*, void*))
{
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			//如果前者大于后者,也就是降序,会返回一个大于0的数(根据这个cmp的函数来的)
			//不知道是啥类型,强制转换为最小的就行(类型占字节最小的是字符型)
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);//采用冒泡的方式
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

  • 30
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 24
    评论
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我要学编程(ಥ_ಥ)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值