一 写在开头
1.1 本节内容
学习C语言中的qsort()函数。

二 qsort()
2.1 函数原型

void qsort(
void *base,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *)
);

函数功能:qsort()函数的功能是对数组进行排序,数组有nmemb个元素,每个元素大小为size。

参数base       - base指向数组的起始地址,通常该位置传入的是一个数组名
参数nmemb  - nmemb表示该数组的元素个数
参数size        - size表示该数组中每个元素的大小(字节数)
参数(*compar)(const void *, const void *) - 此为指向比较函数的函数指针,决定了排序的顺序。

函数返回值:无

注意:如果两个元素的值是相同的,那么它们的前后顺序是不确定的。也就是说qsort()是一个不稳定的排序算法。

2.2 compar参数
compar参数指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型,同时在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也必须转换成const void *型。在compar函数内部会将const void *型转换成实际类型,见下文。

int compar(const void *p1, const void *p2);

如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面
因此,如果想让qsort()进行从小到大(升序)排序,那么一个通用的compar函数可以写成这样:

 int compareMyType (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -;
if ( *(MyType*)a == *(MyType*)b ) return ;
if ( *(MyType*)a > *(MyType*)b ) return ;
}

注意:你要将MyType换成实际数组元素的类型。

2.3 一个使用qsort()函数的小例子

 /* qsort example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */ int values[] = { , , , , , }; int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
} int main ()
{
int n;
qsort (values, , sizeof(int), compare);
for (n=; n<; n++)
printf ("%d ",values[n]);
return ;
}

分析一下compar函数。如果a小于b,则返回值为负数(< 0),也即a会排在b的前面。同理,若a大于b,则a会排在b的后面。所以,这里的qsort()为从小到大即升序排序。因此,运行结果为:10 20 25 40 90 100

2.4 修改compar(),使qsort()为降序排序
很简单,只要将上面compare()中的

return ( *(int*)a - *(int*)b );

改为:

return ( *(int*)b - *(int*)a );

即可,想想为什么可以。

2.5 改写

可以将上面的小例子改写如下:

/* qsort example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */ int values[] = {, , , , , };
const unsigned long VALUES_LEN = sizeof(values) / sizeof(values[]);
const unsigned long VALUES_ITEM_SIZE = sizeof(values[]); int compare(const void * a, const void * b)
{
return (*(int *)a - *(int *)b);
} int main()
{
int i; qsort(values, VALUES_LEN, VALUES_ITEM_SIZE, compare);
for (i = ; i < VALUES_LEN; i++)
{
printf("%d ", values[i]);
}
putchar('\n'); return ;
}

改写的目的是尝试增强程序的健壮性,但我不知道这种方法的好坏,还请各位大神多多指教如何将代码写好。

三 参考资料
1. qsort - C++ Reference
2. man qsort

qsort()函数详解的更多相关文章

  1. qsort函数详解

    C语言标准库函数 qsort 详解 文章作者:姜南(Slyar) 文章来源:Slyar Home (www.slyar.com) 转载请注明,谢谢合作. 原文链接:http://www.slyar.c ...

  2. scandir函数详解

    scandir函数详解2009-10-30 10:51scandir函数:读取特定的目录数据表头文件:#include <dirent.h>定义函数:int scandir(const c ...

  3. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

  4. NSSearchPathForDirectoriesInDomains函数详解

    NSSearchPathForDirectoriesInDomains函数详解     #import "NSString+FilePath.h" @implementation ...

  5. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  6. Linux C popen()函数详解

    表头文件 #include<stdio.h> 定义函数 FILE * popen( const char * command,const char * type); 函数说明 popen( ...

  7. kzalloc 函数详解(转载)

    用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0. view plain /** * kzal ...

  8. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

  9. jQuery.attr() 函数详解

    一,jQuery.attr()  函数详解: http://www.365mini.com/page/jquery-attr.htm 二,jQuery函数attr()和prop()的区别: http: ...

随机推荐

  1. 如何设置非管理员用户配置特定的IIS站点

    如何设置非管理员用     户配置特定的IIS站点 一.           添加IIS管理服务 二.           启动管理服务 勾选启用远程连接后.点右边的应用 三.           设 ...

  2. Django REST framework基础:分页

    DRF分页组件 为什么要使用分页 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输 ...

  3. isinstance_issubclass

    isinstance和issubclass分别是检验是不是对象是不是类的实例化,和子类是不是这个父类的子类 class A:pass class B(A):pass a = A() print(isi ...

  4. java中 & ^ ~ 的运算

    java运算符 与(&).非(~).或(|).异或(^)   最近看HashMap源码,遇到了这样一段代码: 1 static final int hash(Object key) { 2 i ...

  5. ElasticSearch(八):elasticsearch.yml配置说明

    集群名称:cluster.name: my-application确保在不同的环境中的集群的名称不重复,否则,节点可能会连接到错误的集群上 节点名称:node.name: node-1默认情况下,当节 ...

  6. UVA10054-The Necklace(无向图欧拉回路——套圈算法)

    Problem UVA10054-The Necklace Time Limit: 3000 mSec Problem Description Input The input contains T t ...

  7. HyperLedger Fabric ChainCode开发——shim.ChaincodeStubInterface用法

    深蓝前几篇博客讲了Fabric的环境搭建,在环境搭建好后,我们就可以进行Fabric的开发工作了.Fabric的开发主要分成2部分,ChainCode链上代码开发和基于SDK的Application开 ...

  8. SQL Server中NULL的一个测试

    我们都知道SQL Server中NULL是一个很特殊的存在,因为NULL不会等于任何值,且NULL也不会不等于任何值.对于NULL我们只能使用IS或IS NOT关键字来进行比较. 我们先来看看下面一个 ...

  9. 「学习笔记」min_25筛

    前置姿势 魔力筛 其实不看也没关系 用途和限制 在\(\mathrm{O}(\frac{n^{0.75}}{\log n})\)的时间内求出一个积性函数的前缀和. 所求的函数\(\mathbf f(x ...

  10. vue中使用Base64和md5和rsa

    https://blog.csdn.net/benben513624/article/details/88113459(copy) https://www.cnblogs.com/myfate/p/1 ...