回调函数,以qsort函数为例

简介: 回调函数,以qsort函数为例
一、作者声明:

标题中的可爱纯纯是用来凑字数,没有特殊含义,因为可爱的平台不让用四个字作为标题!

如果平台允许我甚至想用两个字作为标题——《回调》!或者直接一个字——《调》!

二、什么回调函数?

通过函数指针调用的函数就是回调函数。

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

三、库函数qsort为例,讲解回调函数

qsort函数:快速排序函数

qsort是一个库函数,底层使用的是快速排序的方式,对数据进行排序。该函数可以直接使用,能对任意类型的数据进行排序。

包含于头文件:

#include<stdlib.h>

函数原型:

void qsort (void* base, size_t num, size_t size, int (*compar)(const void* e1,const void* e2))

参数解析:

void *base是待排序数组第一个元素的地址(起始地址)

size_t num是待排序数组的大小(元素个数)

size_t num是待排序数组元素的大小(每一个元素的字节大小)

int (*compar)(const void* e1,const void* e2)是函数指针,指向比较函数(不同类型数据的比较方法不同,因此需要自定义比较方法),该函数返回值为int类型,参数为e1,e2,分别是待比较两个元素的地址。返回值要求:

若e1指向的元素大于e2指向的元素,则返回大于0的数字;若相等,则返回0;若小于,则返回小于0的数字。

(注1:正是因为有了compar比较函数,qsort函数才能排序任意类型的数据)

(注2:void *类型指针不能直接解引用,也不能加减整数,它是用来存放任意类型数据的地址,使用时需要强制类型转换)

实例代码1(排序整型数据):

void Printnums(int* nums, size_t size)//打印整型数组函数
{
  int i = 0;
  for (i = 0; i < size; i++)
  {
    printf("%d ", nums[i]);
  }
}
int cmp_int(const void* e1, const void* e2)//整形数据的比较函数
{
  return *(int*)e1 - *(int*)e2;//无具体类型指针先强制类型转换,再解引用
}
int main()
{
  int nums[10] = { 10,9,8,7,6,5,4,3,2,1 };
  qsort(nums, sizeof(nums) / sizeof(nums[0]), sizeof(nums[0]), cmp_int);
    //待排序数组起始地址;待排序数组元素个数;待排序数组每个元素的字节大小;数据比较函数
  Printnums(nums, sizeof(nums) / sizeof(nums[0]));
  return 0;
}

实例代码2(按年龄大小排序结构体数组):

struct stu {
  char name[20];
  int age;
};
void Print_struct_age(struct stu* arr,size_t size)//打印结构体数组中结构体成员变量—年龄
{
  for (int i = 0; i < size; i++)
  {
    printf("%d ", arr[i].age);
  }
  printf("\n");
}
int cmp_struct_age(const void* e1, const void* e2)//按照年龄比较排序
{
  return ((struct stu*)e1)->age - ((struct stu*)e2)->age;//强制类型转换为结构体指针类型,不解引用利用->也可以访问成员变量
}
int main()
{
  struct stu s1 = { "Tom",29 };//结构体变量
  struct stu s2 = { "Jerry",20 };
  struct stu s3 = { "David",26 };
  struct stu arr[] = { s1,s2,s3 };//结构体数组
  Print_struct_age(arr, sizeof(arr) / sizeof(arr[0]));//打印年龄
  qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp_struct_age);//按年龄排序
  Print_struct_age(arr, sizeof(arr) / sizeof(arr[0]));//打印年龄
  return 0;
}

实例代码3(按姓名首字母排序结构体数组):

struct stu {
  char name[20];
  int age;
};
void Print_struct_name(struct stu* arr,size_t size)//打印结构体数组中结构体成员变量—姓名
{
  for (int i = 0; i < size; i++)
  {
    printf("%s ", arr[i].name);
  }
  printf("\n");
}
int cmp_struct_name(const void* e1, const void* e2)
{
  return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);//利用strcmp字符串比较函数,该函数的返回值要求和qsort中compar比较函数的返回值要求相同
}
int main()
{
  struct stu s1 = { "Tom",29 };//结构体变量
  struct stu s2 = { "Siri",20 };
  struct stu s3 = { "David",26 };
  struct stu arr[] = { s1,s2,s3 };//结构体数组
  Print_struct_name(arr, sizeof(arr) / sizeof(arr[0]));//打印姓名
  qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp_struct_name);//按姓名首字母排序
  Print_struct_name(arr, sizeof(arr) / sizeof(arr[0]));//打印姓名
  return 0;
}

以上所有实例都是利用qsort快速排序函数对各种类型的数据排序,当我们向qsort函数参数传入比较函数compar地址时,该函数在qsort函数中通过其函数指针被调用,就是回调函数。

目录
相关文章
|
6月前
|
C语言
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
72 0
|
1月前
|
C++
指针中的回调函数与qsort的深度理解与模拟
本文详细介绍了回调函数的概念及其在计算器简化中的应用,以及C++标准库函数qsort的原理和使用示例,包括冒泡排序的模拟实现。
17 1
|
算法 程序员 C语言
【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)
回调函数为C语言重要知识点,以函数指针为主要知识;下面介绍回调函数的定义、回调函数的库函数举例即库函数模拟实现。
52 0
【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)
|
11月前
回调函数与qsort函数
回调函数与qsort函数
40 0
【指针的进阶(3)】回调函数和qsort排序各种类型的数据
【指针的进阶(3)】回调函数和qsort排序各种类型的数据
55 0
|
存储 编译器 C语言
回调函数的应用(sqort函数)——指针进阶(三)
回调函数的应用(sqort函数)——指针进阶(三)
35 0
|
编译器 C语言
C语言之回调函数,qsort函数的定义及使用方法
C语言之回调函数,qsort函数的定义及使用方法
|
C语言 C++
深入理解回调函数qsort:从入门到模拟实现(下)
深入理解回调函数qsort:从入门到模拟实现(下)
45 0
|
搜索推荐 C语言
深入理解回调函数qsort:从入门到模拟实现(上)
深入理解回调函数qsort:从入门到模拟实现(上)
84 0
|
C语言
【c语言进阶】还在自己写排序的函数吗?快来通过回调函数学习并模拟库函数 qsort 的实现把
【c语言进阶】还在自己写排序的函数吗?快来通过回调函数学习并模拟库函数 qsort 的实现把
54 0