海口建站模板,建设网站的市场分析,服装技术支持东莞网站建设,怎么查看网站备案号前言#xff1a;对于库函数有适当了解的朋友们#xff0c;对于 qsort 函数想必是有认知的#xff0c;因为他可以对任意数据类型进行排序的功能属实是有点厉害的#xff0c;本次分享#xff0c;笔者就给大家带来 qsort 函数的全面的解读 本次知识的分享笔者分为上下俩卷文章… 前言对于库函数有适当了解的朋友们对于 qsort 函数想必是有认知的因为他可以对任意数据类型进行排序的功能属实是有点厉害的本次分享笔者就给大家带来 qsort 函数的全面的解读 本次知识的分享笔者分为上下俩卷文章进行讲解在本篇文章中给大家带来 qsort 函数的基础认知以及他如何进行功能实现的背后原理讲解 目录
一.什么是 qsort 函数
二. qsort 的使用
1.对于整形数组的排序
2.对于浮点型数组的排序
3.对于结构体数组的排序
通过姓名首字母排序
通过年龄进行排序 一.什么是 qsort 函数
我们打开 cplusplus 网站查看详细定义 qsort - C Reference (cplusplus.com) 在官方的定义中是这样说的 对所指向的数组元素进行排序每个元素长度为字节使用函数确定顺序此函数使用的排序算法通过调用指定的函数将指向元素的指针作为参数来比较元素对该函数不返回任何值但通过重新排序所定义的元素来修改所指向数组的内容等效元素的顺序未定义 翻译成我们自己的语言就是这个函数是用来对数组元素排序的我们自己用函数来确定排序的规则 并且对于数组元素的类型是没有作任何要求的这也就意味着我们可以对任意类型的元素进行任意规则的排序 还是看上图这个函数有 4 个参数并且不进行返回值我们接下来分别解析一下具体是怎么样的一个意思 void qsort (void* base, size_t num,size_t size,int (*compar)(const void*, const void*)); 对于这样的文本我们还是要转化为自己好理解的方式 void* base待排序数组的第一个元素的地址size_t num待排序数组的元素个数size_t size待排序数组中一个元素的大小int (*compar)(const void*, const void*)函数指针-cmp指向了一个函数这个函数是用来比较两个元素的e1和e2中存放的是需要比较的两个元素的地址 另外对于第 4 点也就是具体比较方法的函数它的返回值是需要注意的只返回三类值大于零等于零小于零具体含义在后文实例中进行讲解这里就不再多做赘述 二. qsort 的使用
1.对于整形数组的排序
我们定义一个整型数组 int arr1[10] { 0,1,2,3,4,5,6,7,8,9 };
然后定义一个函数打印数组方便我们观察
void print1(int* arr)
{for (int i 0; i 10; i){printf(%d , *(arr i));}printf(\n);
}
然后我们调用 qsort 进行排序在这里我们详细的看看四个参数
第一个参数 arr1指向数组arr1我们就得到了需要排序的数组的第一个元素的地址第二个参数 10代表的是这个数组的大小是 10第三个参数 4代表的是数组元素的字节大小arr1 是个整形数组整形 int 是 4 个字节所以这里的参数是4第四个参数 comp_int这是个函数更是它这个函数本身的地址我们将这里的函数地址作为参数就可以调用我们的判断规则的函数
qsort(arr1, 10, 4, comp_int);
int comp_int(const void* a,const void* b)
{return *(int*)b - *(int*)a;
} 判断函数这里更是我们需要注意的地方我们进入到判断函数中这个判断函数又有俩个参数都是 void* 的类型这样设定的目的是为了拿到一个地址为了泛型编程的思想我们这里只管拿到地址不需要思考怎么处理这俩个地址所以使用 void* 这样就能满足更多的需求后期我们想要更改判断条件的话也只需要更改这个函数内部的数据不影响我们整体传参这是一种非常高级的编程思想我们可以进行适当的学习同时在公司内部编程的时候往往是很多人进行编程一个程序这样设置更是为了方便这种团队编程的思想和功能 进入函数体我们首先先确定我们的具体需求我们要的是俩个整数进行比较但是这里我们拿到的地址是 void* 类型的所以我们需要进行强制转化把俩个参数转化为整形这样才能满足我们的需求拿到整形地址后对其解引用就可以访问里面的数据然后进行判断了这里我们设置的是如果 ba 就返回正值也就是后面的数字大于前面的数字的情况下我们才进行交换 输出结果实例如下我们可以看见对于原本升序的数组经过我们的排序后就变成了降序 int arr1[10] { 0,1,2,3,4,5,6,7,8,9 };print1(arr1);qsort(arr1, 10, 4, comp_int);print1(arr1); 2.对于浮点型数组的排序 和刚才整形数组的排序类似我们定义一个浮点型数组然后在排序前和排序后分别进行打印一次我们这里需要重点观察的是他的判断函数也就是他的第四个参数 float arr2[5] { 1.2,3.4,5.6,7.8,9.9 };print2(arr2);qsort(arr2, 5, sizeof(float), comp_float);print2(arr2); 我们观察判断函数我们发现对于 void* 类型的转化为浮点型指针然后进行解引用访问我们试着运行一下看看可不可以这样写
int comp_float(const void* a, const void* b)
{return *(float*)b - *(float*)a;
} 经过实验我们发现 void* 类型强制转化为浮点型也是可以正常运行的这里也就验证了我们刚才说过的泛型编程的思想 3.对于结构体数组的排序 刚才简单的数据类型我们都实验过了我们好像可以发现这样设置判断函数非常的方便参数内不管接受什么数据类型统一写 void* 类型就可以了那我们现在不妨试一些复杂的数据类型 —— 结构体数组 在一切实验之前我们先得写一个结构体类型还有其对于的结构体数组我们写个学生的结构体内容由学生姓名和年龄组成
struct stu
{char name[20];int age;
};
然后对于结构体数组我们分别如下定义张三19岁李四20岁王五21岁
struct stu arr3[] {{zhangsan,19},{lisi,20},{wangswu,21}}; 做好一切准备工作后我们进行 qsort 排序的设置我们可以分为俩种方式排序一种是用姓名首字母进行排序一种是由年龄大小进行排序
通过姓名首字母排序
我们如下设置我们来看看 qsort 的四个参数
第一个参数 arr3指向的是结构体数组的第一个元素的地址第二个参数 3代表的是这个结构体数组一共有 3 个元素第三个参数 sizeof(arr3[0])代表的是结构体数组的每一个元素的大小这一个元素包含了学生的姓名和年龄第四个参数 comp_name代表的是排序的规则函数 qsort(arr3, 3, sizeof(arr3[0]), comp_name);
int comp_name(const void* a, const void* b)
{return strcmp(((struct stu*)a)-name, ((struct stu*)b)-name);
} 我们还是重点看一下排序规则的函数参数方面还是和我们上面讲的一样俩个 void* 方便我们后期修改进入函数体我们将俩个参数强制转化为结构体类型然后分别指向结构体内部的姓名变量然后我们调用了 strcmp 函数这个函数的功能是比较俩个字符串的首元素的 ACSSII 大小然后进行返回值返回值和外边的比较方法的返回值的格式和大小一模一样如下图 通过年龄进行排序
相较于上述的姓名排序这里的年龄排序就简单的多了 qsort(arr3, 3, sizeof(arr3[0]), comp_age);
int comp_age(const void* a, const void* b)
{return ((struct stu*)b)-age - ((struct stu*)a)-age;
} 我们这里对年龄整体的处理和上述的整形数组的处理是一样的唯一不同的就是我们拿到数据的方式我们先将其强制转换为结构体类型然后通过结构体类型指向的年龄进行比较 通过了上述的实例讲述我们明白了对于任何的数据类型我们在拿这个参数的时候都是用 void* 类型进行取址然后对于具体比较操作的时候我们再将其进行具体的操作强制转化为我们需要的数据类型然后进行排序这样就实现了其 “万能排序” 的功能 下一篇文章我们就探讨如何对 qsort 函数的模拟实现