一 写在开头
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. Boosting Static Representation Robustness for Binary Clone Search against Code Obfuscation and Compiler Optimization(一)

    接着上一篇,现在明确问题:在汇编克隆搜索文献中,有四种类型的克隆[15][16][17]:Type1.literally identical(字面相同):Type2.syntactically equ ...

  2. 我的第一个python web开发框架(22)——一个安全小事故

    在周末的一个早上,小白还在做着美梦,就收到了小美的连环追魂call,电话一直响个不停. 小白打着哈欠拿起电话:早上好美女. 小美:出事了出事了,我们公司网站一早访问是一片空白,什么内容都没有了,你赶急 ...

  3. SAP Change Request Management (ChaRM)基础教程

    本文介绍了SAP Solution Manager中的变更请求管理工具(Change Request Management,以下简称ChaRM ). 最近打算写个上线前请求号检查工具,为此需要了解相关 ...

  4. RabbitMQ广播:fanout模式

    一. 消息的广播需要exchange:exchange是一个转发器,其实把消息发给RabbitMQ里的exchange fanout: 所有bind到此exchange的queue都可以接收消息,广播 ...

  5. RabbitMQ安装,Windows下

    一.下载安装ERLANG语言 otp_win64_20.3.exe 一直下一步.然后设置环境变量  ERLANG_HOME   C:\Program Files\erl9.3 二.安装RabbitMQ ...

  6. Linux下的快速配置虚拟环境virtualenvwrapper

    一 安装包 pip3 install virtualenv virtualenvwrapper 二 设置linux的用户个人配置文件~/.bashrc WORKON_HOME=~/Envs 设置vir ...

  7. 【Python 09】汇率兑换2.0-2(分支语句)

    分支语句:根据判断条件选择程序执行路径 1.使用方法 if <条件1>: <语句块1> elif <条件2>: <语句块2> ... else: < ...

  8. .NET ORM框架之NHibernate

    这段时间一直使用NHibernate,今天抽空总结一下. 1.什么是NHibernate? NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/r ...

  9. 【转】JSON.parse() Unexpected token i in JSON at position 2 报错问题

    JSON.parse(): Unexpected token i in JSON at position 2 报错问题 错误代码: var res = "[{id:1,name:'limin ...

  10. TortoiseGit之配置密钥

    TortoiseGit 使用扩展名为ppk的密钥,而不是ssh-keygen生成的rsa密钥.使用命令ssh-keygen -C "邮箱地址" -t rsa产生的密钥在Tortoi ...