⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:C语言进阶
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!

qsort函数

  • 前言
  • qsort函数
    • (一)引例:简单的冒泡排序
    • (二)qsort函数接收
      • 1.介绍
      • 2.void*
    • (三)使用
      • 1.用qsort实现一个比较整型的函数
      • 2.用qsort实现一个比较结构体的函数
      • 3.用qsort实现一个比较浮点型的函数
    • (四)用冒泡排序模拟qsort函数的使用
      • 1.模拟qsort实现一个比较整数的函数
      • 2.模拟qsort实现一个比较结构体的函数
      • 3.模拟qsort实现一个比较浮点型的函数
  • 总结

前言

在学习回调函数的时候,不免会觉得难以理解或者难以运用,那就需要引入一个例子qsort库函数来让大家理解理解真正的回调函数是怎么样的,这就需要我们进行深入的了解什么是qsort函数,我们是先根据MSDN去查了查什么是qsort,然后就依据它的本质进行演示了不同类型的数的排序,最后模拟了一下冒泡排序运用qsort函数的使用,这都是干货满满!!!


qsort函数

要了解qsort函数,那就需要先引进一个简单的冒泡函数:

(一)引例:简单的冒泡排序

#include<stdio.h>//缺陷:只能排序函数
bubble_sort(int* arr, int sz) {int i = 0;for (i = 0; i < sz - 1; i++) {int j = 0;for (j = 0; j < sz - 1 - i; j++) {if (*(arr + j) > *(arr + j + 1)) {int temp = *(arr + j);*(arr + j) = *(arr + j + 1);*(arr + j + 1) = temp;}}}
}
int main() {//对数组进行排序,升序int arr[10] = { 0,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);//打印int i = 0;for (i = 0; i < sz; i++) {printf("%d ", arr[i]);}return 0;
}

似乎有点缺陷啊,那我们要排字符呢?排结构体呢?是不是没法用大于号小于号和等于号进行比较了,那我们是不是需要把这个比较的式子单独抽离出来,在单独空间进行比较。

(二)qsort函数接收

1.介绍



2.void*

如果我们用整型指针去接收浮点型指针的时候,出现不兼容的情况,所以qsort的作者也考虑到了这一情况,既然不兼容,那我们找一个典当行,我用什么类型的指针传递给他(什么废铜烂铁都给他),他肯定看看不报错,因为总是有值钱的嘛,那这个典当行就是void*即空类型的指针。


所以我们为什么要用void*来接收传参呢?

我们发现float*到int*是不匹配的,那我们就需要void*了。

#include<stdio.h>int main() {int a = 10;float f = 5.5f;int* p = &a;//p = &f;//好处://pp为通用的指针,什么地址都可以放到pp指针里面//void*自己都不知道自己是什么类型的指针void* pp = &f;pp = &a;//弊端://void*指针不能直接用,不能直接进行运算和打印pp++;//err void*未知的大小printf("%f\n", *pp);//err 非法的间接寻址return 0;
}


这个典当行行长void*说你们可以把不同的指针类型丢给我但是我也有条件的,你给我的什么破铜烂铁啊!我不输出了,你让我加价!?那肯定不可能的,可是我们想要达到我们的目的怎么办呢?我们就需要用暴力手段了,强制类型转换,跟典当行老板说,你今天必须给我加价并报出我满意的价格,不然告你黑店,典当行行长说,好好好,少侠饶命,我肯定加价报出好价格,这下子只要进行强制类型转换就好了。

如下图进行:

(三)使用

1.用qsort实现一个比较整型的函数

思路是利用qsort函数进行比较函数传参,即cmp_int函数,这个函数就是我们的回调函数,因为它进行传递地址给asort函数,qsort函数接收了cmp_int函数的地址并进行回调,回调以后接受比较的两个元素进行强制类型转换为整型指针进行相加减,根据qsort函数的返回值进行排序升序还是降序。
代码如下:

#include<stdio.h>
#include<stdlib.h>
//实现一个比较整型的函数
int cmp_int(const void* elem1, const void* elem2) {return *(int*)elem1 - *(int*)elem2;//升序//return *(int*)elem2 - *(int*)elem1;//降序
}
//使用qsort函数对数组进行排序,升序
void test1(void) {//对数组进行排序,升序int arr[10] = { 0,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);//bubble_sort(arr, sz);//库函数中有一个专门排序的函数叫qsortqsort(arr, sz, sizeof(arr[0]), &cmp_int);//&cmp_int是取出函数的地址并进行回调//打印int i = 0;for (i = 0; i < sz; i++) {printf("%d ", arr[i]);}
}int main() {test1();//test2();return 0;
}

2.用qsort实现一个比较结构体的函数

思路是跟上面相似,而结构体这边要用的是要定义一个结构体并进行定义结构体数组,这里用到的技巧是结构体指针用的是->,还有一个比较强的技巧是strcmp,这里的strcmp库函数的返回值与qsort函数的返回值完全一致,我们打开MSDN看看:

结构体内元素类型不同不能进行比较哦,只能进行比较同类型的元素。
代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//使用qsort函数排序结构体
struct Stu {char name[30];int age;
};
//先按照年龄排序
int cmp_stu_by_age(const void* elem1, const void* elem2) {return ((struct Stu*)elem1)->age - ((struct Stu*)elem2)->age;
}
//再按照名字排序
int cmp_stu_by_name(const void* elem1, const void* elem2) {return strcmp(((struct Stu*)elem1)->name, ((struct Stu*)elem2)->name);
}
void test2(void) {struct Stu s[3] = { {"zhangsan",20 },{"lisi",32},{"wangwu",55} };int sz = sizeof(s) / sizeof(s[0]);//qsort(s, sz, sizeof(s[0]), &cmp_stu_by_age);qsort(s, sz, sizeof(s[0]), &cmp_stu_by_name);int i = 0;for (i = 0; i < sz; i++) {printf("%s %d\n", s[i].name, s[i].age);}
}int main() {//test1();test2();return 0;
}

3.用qsort实现一个比较浮点型的函数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp_float(const void* elem1, const void* elem2) {if (*(float*)elem1 > *(float*)elem2){return 1;}else if (*(float*)elem1 < *(float*)elem2){return -1;}else {return 0;}
}
void test3(void) {//对数组进行排序,升序float arr[] = { 0.3, 0.4, 0.1, 0.2, 0.5 };int sz = sizeof(arr) / sizeof(arr[0]);//bubble_sort(arr, sz);//库函数中有一个专门排序的函数叫qsortqsort(arr, sz, sizeof(arr[0]), &cmp_float);//打印int i = 0;for (i = 0; i < sz; i++) {printf("%.1f ", arr[i]);}
}
int main() {//test1();//test2();test3();return 0;
}

(四)用冒泡排序模拟qsort函数的使用

1.模拟qsort实现一个比较整数的函数

先上代码再分析:

#include<stdio.h>//改造冒泡排序函数,使用这个函数可以排序任意指定的数组
int cmp_int(const void* elem1, const void* elem2) {return *(int*)elem1 - *(int*)elem2;//升序//return *(int*)elem2 - *(int*)elem2;//降序
}void Swap(char* buf1, char* buf2, int width) {int i = 0;for (i = 0; i < width; i++) {int temp = *buf1;*buf1 = *buf2;*buf2 = temp;buf1++;buf2++;}
}
//base就是未知参数的起始地址,
//sz就是传过来的数组大小,
//width是传过来数组内一个元素的字节长度
//int (*cmp)(const void*elem1, const void*elem2)是比较方法
//void*的意思就是不知道要传的是什么类型
bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void*elem1, const void*elem2)) {int flag = 1;size_t i = 0;for (i = 0; i < sz - 1; i++) {size_t j = 0;for (j = 0; j < sz - 1 - i; j++) {if (cmp((char*)base+j*width, (char*)base+(j+1)*width) > 0) {//交换Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);flag = 0;}}if (flag) {break;}}
}
//使用自己写的bubble_sort排序整型数组
void test3(void) {//对数组进行排序,升序int arr[10] = { 0,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), &cmp_int);//打印int i = 0;for (i = 0; i < sz; i++) {printf("%d ", arr[i]);}
}
int main() {//test3();test4();return 0;
}

大家可以点开图片一点一点看,这个图片有点大。

细节:


2.模拟qsort实现一个比较结构体的函数

先上代码再分析:

#include<stdio.h>
//使用自己写的bubble_sort排序结构体数组
struct Stu {char name[30];int age;
};
//先按照年龄排序
int cmp_stu_by_age(const void* elem1, const void* elem2) {return ((struct Stu*)elem1)->age - ((struct Stu*)elem2)->age;
}
//再按照名字排序
int cmp_stu_by_name(const void* elem1, const void* elem2) {return strcmp(((struct Stu*)elem1)->name, ((struct Stu*)elem2)->name);
}
void test4(void) {struct Stu s[3] = { {"zhangsan",20 },{"lisi",32},{"wangwu",55} };int sz = sizeof(s) / sizeof(s[0]);bubble_sort(s, sz, sizeof(s[0]), &cmp_stu_by_age);//bubble_sort(s, sz, sizeof(s[0]), &cmp_stu_by_name);int i = 0;for (i = 0; i < sz; i++) {printf("%s %d\n", s[i].name, s[i].age);}
}
int main() {//test3();test4();return 0;
}

比较结构体就和前面的qsort函数一样了,只不过换了个名字,因为要用到的都是地址。

3.模拟qsort实现一个比较浮点型的函数

比较浮点型的就需要考虑考虑了,那为了方便起见我们还是比较大小吧,如果相加减精度超过了范围那就不好办了,所以还是直接判断大小更加稳妥一点。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//使用自己写的bubble_sort排序浮点型数组
int cmp_float(const void* elem1, const void* elem2) {if (*(float*)elem1 > *(float*)elem2) {return 1;}else if (*(float*)elem1 < *(float*)elem2) {return -1;}else {return 0;}
}void Swap(char* buf1, char* buf2, int width) {size_t i = 0;for (i = 0; i < width; i++) {int temp = *buf1;*buf1 = *buf2;*buf2 = temp;buf1++;buf2++;}
}void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* elem1, const void* elem2)) {int flag = 0;size_t i = 0;for (i = 0; i < sz - 1; i++) {size_t j = 0;for (j = 0; j < sz - 1 - i; j++) {if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) {Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);flag = 1;}}if (flag) {break;}}}void test5(void) {//对数组进行排序,升序float arr[] = { 0.1,0.3,0.2,0.4,0.5 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), &cmp_float);//打印int i = 0;for (i = 0; i < sz; i++) {printf("%.1f ", arr[i]);}
}
int main() {//test3();//test4();test5();return 0;
}

总结

总的来讲,qsort函数是很有趣的,当我们一步步去探索,一步步去剖析,会发现很多有趣的库函数,这篇博客细致讲解了qsort函数的使用,先是很细致的讲解了qsort函数的介绍以及使用,再是以一个冒泡排序的思想模拟实现了一个比较不同类型的函数,可谓是干货满满!


客官,码字不易,来个三连支持一下吧!!

【C进阶】qsort函数详解相关推荐

  1. qsort函数详解以及模拟实现

    qsort函数详解以及模拟实现 一.qsort函数是什么 二.具体的使用 1.参数4(参数3在模拟实现时解释) 2.例子 1.排序整形 2.排序结构体 三.模拟实现qsort 1.参数3 2.模拟排序 ...

  2. 冒泡排序和qsort函数详解以及如何模拟实现qsort函数

    一.冒泡排序 冒泡排序是一种常见的排序方式,它可以把数组元素有序或无序的数组进行重新排序,并使得数组中的元素从大到小或从小到大进行排序(就像泡泡一样). 冒泡排序原理: 每次比较数组中的相邻的两个元素 ...

  3. 【C库函数】qsort函数详解

    目录 qsort ​ 函数基本原型 参数解读 函数详解 比较函数实现并解读 qsort函数排序代码实现并展示结果 1.排序整型数组 2.排序结构体 qsort 函数是基于快速排序算法实现的一个排序函数 ...

  4. C语言-qsort函数详解

    目录 一.qsort函数是什么 二.使用qsort排序-以升序为例 关于void*型指针: 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒 ...

  5. qsort()函数详解

    一.写在开头 1.1 本节内容 学习C语言中的qsort()函数. 二.qsort() 2.1 函数原型 void qsort(void *base,size_t nmemb,size_t size, ...

  6. C语言-qsort函数详解及使用例

    q s o r t ( ) qsort() qsort() 函数是C语言 srdlib.h 库中的排序函数.此函数使用快速排序算法,时间复杂度一般在 O ( l g ( n ) ) O(lg(n)) ...

  7. C语言 qsort()函数详解 (笔记)

    qsort函数,其声明在stdlib.h文件中,时间复杂度为n*log(n). 功能:使用快速排序例程进行排序 用法: void qsort(void *base, size_t nitems, si ...

  8. C语言 快速排序——qsort函数详解

    我们在使用冒泡排序法做题的时候,经常会遇到运算次数过多程序超时的情况,而且冒泡排序法只能对整形数组进行排序. 为了解决这些问题!就使用qsort函数吧! 目录 一.qsort函数使用方法 二.qsor ...

  9. C语言 - qsort函数详解

    文章目录 一.qsort函数简介 1.qsort函数是C标准库<stdlib.h>库中的函数,使用时引入#include <stdlib.h>.** 2.它的函数原型是 voi ...

最新文章

  1. 2021-01-26 粒子群优化算法(PSO)以及Matlab实现
  2. editplus的使用技巧
  3. 职场警示录:怎样和“小人”和睦相处
  4. idefo功能模型图_利用好预后预测模型,2个月发篇4分+SCI不是梦
  5. python实现knn算法鸢尾花_Python学习之knn实现鸢尾花分类
  6. 逼自己玩命学了3个多月,整理出了这份549个分支的技术脑图,分享给你
  7. python matplotlib 保存图片失真_Python matplotlib线框失真
  8. java案例代码3-机票打折的案例
  9. 新闻资讯android版
  10. 跨境电商四大推广路径都有哪些?站斧浏览器带你挑选最适合你的引流渠道
  11. HTTPS原理、单向和双向认证
  12. MySQL编程:将查询到的字段赋值给变量
  13. 基于LSTM实现股票预测
  14. 趣头条:资讯界的拼多多?
  15. Switch游戏机Type-C底座方案
  16. C++实现二路归并排序算法
  17. 理解windows消息通告消息和命令消息!!!
  18. 强大的矩阵奇异值分解(SVD)及其应用(转)-我们老师推荐的
  19. Unity SKFramework框架(二十一)、Texture Filter 贴图资源筛选工具
  20. FME进阶视频教程:第1节 FME常用转换器之字符串操作类1

热门文章

  1. 要闻君说:阿里云联合8家芯片模组商推出“全平台通信模组”;北汽与小桔车服联合“京桔”;IBM要帮助印度公司打造5G战略!...
  2. 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。编写一个程序,使用栈判定给定的字符序列是否为回文。
  3. 什么是DDL和DML语句?
  4. AI TIME 祝清华大学111周年生日快乐!
  5. Action Recognition Using Attention-Joints Graph Convolutional Neural Networks翻译
  6. 程序员的10大老大难问题
  7. 理解目标检测中的老大难:小目标检测
  8. ES Elasticsearch
  9. 产品管理工具和项目管理工具
  10. BDTC 2017丨探索大数据在医疗行业的应用实践