php内核函数手册,php内核函数natsort浅析

今天发现了PHP有个自然排序的函数----natsort,第一次听说了原来还有一种叫做“自然排序”的算法,很好奇,官方手册(http://us.php.net/manual/en/function.natsort.php)bool natsort ( array &$array )

This function implements a sort algorithm that orders alphanumeric strings in the way a human being would while maintaining key/value associations. This is described as a "natural ordering". An example of the difference between this algorithm and the regular computer string sorting algorithms (used in sort()) can be seen in the example below.

据官方手册还可以得到这样的结果:

img1.png img2.png img10.png img12.png

显然这很适合对类似文件名的排序。从结果看这种自然算法应该是去掉头和尾的非数字部分,然后对留下来的数字部分进行排序,究竟是不是,还是看一下php源码吧。//从ext/standard/array.c抽取的相关代码如下

static int php_array_natural_general_compare(const void *a, const void *b, int fold_case) /* {{{ */

{

Bucket *f, *s;

zval *fval, *sval;

zval first, second;

int result;

f = *((Bucket **) a);

s = *((Bucket **) b);

fval = *((zval **) f->pData);

sval = *((zval **) s->pData);

first = *fval;

second = *sval;

if (Z_TYPE_P(fval) != IS_STRING) {

zval_copy_ctor(&first);

convert_to_string(&first);

}

if (Z_TYPE_P(sval) != IS_STRING) {

zval_copy_ctor(&second);

convert_to_string(&second);

}

result = strnatcmp_ex(Z_STRVAL(first), Z_STRLEN(first), Z_STRVAL(second), Z_STRLEN(second), fold_case);

if (Z_TYPE_P(fval) != IS_STRING) {

zval_dtor(&first);

}

if (Z_TYPE_P(sval) != IS_STRING) {

zval_dtor(&second);

}

return result;

}

/* }}} */

static int php_array_natural_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */

{

return php_array_natural_general_compare(a, b, 0);

}

/* }}} */

static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */

{

zval *array;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {

return;

}

if (fold_case) {

if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) {

return;

}

} else {

if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_compare, 0 TSRMLS_CC) == FAILURE) {

return;

}

}

RETURN_TRUE;

}

/* }}} */

/* {{{ proto void natsort(array &array_arg)

Sort an array using natural sort */

PHP_FUNCTION(natsort)

{

php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);

}

/* }}} */

然是第一次查看php的内核代码,不过凭借多年看代码的经验,还是很容易找到这个自然排序算法的核心就是函数:strnatcmp_ex(位于ext/standard/strnatcmp.c文件中)。/* {{{ compare_right

*/

static int

compare_right(char const **a, char const *aend, char const **b, char const *bend)

{

int bias = 0;

/* The longest run of digits wins. That aside, the greatest

value wins, but we can't know that it will until we've scanned

both numbers to know that they have the same magnitude, so we

remember it in BIAS. */

for(;; (*a)++, (*b)++) {

if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&

(*b == bend || !isdigit((int)(unsigned char)**b)))

return bias;

else if (*a == aend || !isdigit((int)(unsigned char)**a))

return -1;

else if (*b == bend || !isdigit((int)(unsigned char)**b))

return +1;

else if (**a < **b) {

if (!bias)

bias = -1;

} else if (**a > **b) {

if (!bias)

bias = +1;

}

}

return 0;

}

/* }}} */

/* {{{ compare_left

*/

static int

compare_left(char const **a, char const *aend, char const **b, char const *bend)

{

/* Compare two left-aligned numbers: the first to have a

different value wins. */

for(;; (*a)++, (*b)++) {

if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&

(*b == bend || !isdigit((int)(unsigned char)**b)))

return 0;

else if (*a == aend || !isdigit((int)(unsigned char)**a))

return -1;

else if (*b == bend || !isdigit((int)(unsigned char)**b))

return +1;

else if (**a < **b)

return -1;

else if (**a > **b)

return +1;

}

return 0;

}

/* }}} */

/* {{{ strnatcmp_ex

* call in array.c: strnatcmp_ex(Z_STRVAL(first), Z_STRLEN(first), Z_STRVAL(second), Z_STRLEN(second), fold_case);

*/

PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, int fold_case)

{

char ca, cb;

char const *ap, *bp;

char const *aend = a + a_len,

*bend = b + b_len;

int fractional, result;

if (a_len == 0 || b_len == 0)

return a_len - b_len;

ap = a;

bp = b;

while (1) {

ca = *ap; cb = *bp;

/* skip over leading spaces or zeros */

while (isspace((int)(unsigned char)ca) || (ca == '0' && (ap+1 < aend) && (*(ap+1)!='.')))

ca = *++ap;

while (isspace((int)(unsigned char)cb) || (cb == '0' && (bp+1 < bend) && (*(bp+1)!='.')))

cb = *++bp;

/* process run of digits */

if (isdigit((int)(unsigned char)ca) && isdigit((int)(unsigned char)cb)) {

fractional = (ca == '0' || cb == '0');

if (fractional)

result = compare_left(&ap, aend, &bp, bend);

else

result = compare_right(&ap, aend, &bp, bend);

if (result != 0)

return result;

else if (ap == aend && bp == bend)

/* End of the strings. Let caller sort them out. */

return 0;

else {

/* Keep on comparing from the current point. */

ca = *ap; cb = *bp;

}

}

if (fold_case) {

ca = toupper((int)(unsigned char)ca);

cb = toupper((int)(unsigned char)cb);

}

if (ca < cb)

return -1;

else if (ca > cb)

return +1;

++ap; ++bp;

if (ap >= aend && bp >= bend)

/* The strings compare the same. Perhaps the caller

will want to call strcmp to break the tie. */

return 0;

else if (ap >= aend)

return -1;

else if (bp >= bend)

return 1;

}

}

/* }}} */

从strnatcmp_ex函数中的:while (isspace((int)(unsigned char)ca) || (ca == '0' && (ap+1 < aend) && (*(ap+1)!='.')))

ca = *++ap;

while (isspace((int)(unsigned char)cb) || (cb == '0' && (bp+1 < bend) && (*(bp+1)!='.')))

cb = *++bp;

所以,我觉得应该字符串(当前位置开始)中前面的空字符和数字前面的‘0’不会参与比较,比较的结果应该和

http://us.php.net/manual/en/function.natsort.php

http://sourcefrog.net/projects/natsort/example-out.txt

所说的一样,但是在我的php5.2.9中对于“0”的处理结果却不一样(例如“img002.png”与“img1.png”,我的理解应该是前者大于后者,不过在我的5.2.9中却是前者小于后者),原因还没想清楚,可能是5.2.9的一个bug,也可能是自己还没有理解清楚源码的意思。下次配置好环境再好好测试,好好消化~~

在array.c中有两个重要的数据结构很值得我们关注:

Bucket: http://www.phpchina.cn/bbs/viewthread.php?tid=88505

zval: http://www.laruence.com/2008/08/22/412.html

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
08-10
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值