您好,欢迎来到纷纭教育。
搜索
您的当前位置:首页【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

来源:纷纭教育


前言

大家好呀,今天分享一下上期指针进阶中剩余的内容——回调函数,这个很重要滴,让我们一起来学会学懂他吧!!!


一、回调函数是什么

简单来说就是:在另一个函数中利用函数指针调用的函数叫做回调函数

二、回调函数的使用

1.使用标准库中的qsort函数

qsort函数不仅可以排序整型数组,还可以排序结构体等数据类型

代码如下:

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int 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), int_cmp);
    //qsort的第一个参数是排序数组的首元素地址
    //第二个参数是排序的长度
    //第三个参数是每个元素的大小
    //第四参数是使用者自己写的排序依据函数的地址(这里就是使用回调函数)
    for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
   {
       printf( "%d ", arr[i]);
   }
    printf("\n");
    return 0;
}

整型数组排序的运行结果展示:

2.利用qsort函数对结构体数组进行排序

先看代码如下:

#include<stdio.h>
#inlcude<string.h>
struct stu {
	int age;
	char name[20];
	double score;
};
//依据年龄大小排序的比较函数
int compar_by_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
//这是定义一个结构体类型的数组
	struct stu S[3] = { {21,"FRH",100},{19,"MSY",90},{18,"LZY",85} };
	int Ssz = sizeof(S) / sizeof(S[0]);
	qsort(S, Ssz, sizeof(S[0]), compar_by_age);
	qsort(S, Ssz, sizeof(S[0]), compar_by_name);
	return 0;
}

排序前后结果对比:
这是排序前结构体数组的顺序:

三、实现qsort函数

我们先来看一下qsort函数在标准库中的模样:

作者是依据冒泡排序实现的qosrt函数,我们之间上代码:
#include<stdio.h>
#inlcude<string.h>
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
//依据整型大小排序的比较函数
int int_cmp(const void * p1, const void * p2)
{//这里都会将接收到的地址转换为所需要比较的类型
  return (*( int *)p1 - *(int *) p2);
}

//这里排序中交换两个元素的交换函数
void Swap(char* x, char* y,int size)
{
//利用char* 接收需要交换的元素,可以保证对其每个字节进行交换从而实现整体全部字节的交换
//size就是该元素所占字节的大小,决定每次交换循环几次
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char temp = *x;
		*x = *y;
		*y = temp;
		x++;
		y++;

	}
}

void Bubble_Sort(void* base, size_t num, size_t size,int (*compar)(const void*, const void*))
{
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
		//为什么要将首元素地址转换为char* 类型呢?
		//因为:这样可以保证任何类型数组在排序比较时能够访问到其中的每一个元素
		//这个设计是真的巧妙
			if (compar(((char*)base + j * size), ((char*)base + (j+1)*size))>0)
			{
				Swap(((char*)base + j * size), ((char*)base + (j+1)*size), size);
			}
		}
	}
}

对其进行测试:

int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	struct stu S[3] = { {21,"FRH",100},{19,"MSY",90},{18,"LZY",85} };
	int Ssz = sizeof(S) / sizeof(S[0]);
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubble_Sort(arr,sz,sizeof(arr[0]),compar_by_int);
	Print(arr, sz);
	Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_age);
	Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_name);
	return 0;
}

可以得到,排序结果和上面调用标注库中qsort函数的结果是相同的

总结

关于回调函数的分享就到这里啦,希望qsort函数可以帮助到大家,博主感觉他真的是很有用,以后会尽量使用到他的,希望本篇文章可以帮助到大家,谢谢大家阅读!!!

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- fenyunshixun.cn 版权所有 湘ICP备2023022495号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务