php打implode 函数,[PHP源码阅读]explode和implode函数,explodeimplode_PHP教程
[PHP源码阅读]explode和implode函数,explodeimplode
explode和implode函数主要用作字符串-数组的操作,比如获取一段参数后根据某个字符分割字符串,或者将一个数组的结果使用一个字符合并成一个字符串输出。在PHP中经常会用到这两个函数,因此有必要了解一下其原理。
explode
array explode ( string $delimiter, string $string, [ , $limit ] )
返回由字符串组成的数组,每个元素都是string的一个子串,被字符串$delimiter作为边界点分割出来。
$limit
如果设置了$limit,且为正数,则返回的数组最多包含$limit个元素,最后的那个元素将包含$string的剩余部分。
如果$limit是负数,则返回除了最后的-$limit个元素外的所有元素。
如果$limit是0,则会被当做1。
$delimiter
如果$delimiter为空,则函数返回FALSE。如果delimiter不在string中,且$limit为负数,则返回空数组。
核心源码
//如果delimiter为空字符串,返回FALSE
if (delim_len == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Empty delimiter");
RETURN_FALSE;
}//初始化返回的数组
array_init(return_value);if (str_len == 0) {if (limit >= 0) {//如果字符串为空且limit大于等于0,则返回一个包含空字符串的数组,注意此处sizeof("") == 1
add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
}return;
}//初始化zstr和zdelim的字符串变量
ZVAL_STRINGL(&zstr, str, str_len, 0);
ZVAL_STRINGL(&zdelim, delim, delim_len, 0);if (limit > 1) {//limit大于1,limit默认是LONG_MAX
php_explode(&zdelim, &zstr, return_value, limit);
}else if (limit < 0) {//limit 为负数
php_explode_negative_limit(&zdelim, &zstr, return_value, limit);
}else{//limit为0,被当作1处理,返回整个字符串,add_index_stringl函数将str追加到数组return_value中
add_index_stringl(return_value, 0, str, str_len, 1);
}
处理完特殊情况和初始化变量后,就调用php_explode/php_explode_negative_limit函数进行下一步处理。下面是php_explode函数的源码
php_explode
endp= Z_STRVAL_P(str) +Z_STRLEN_P(str);//p1指向字符串的开始
p1 =Z_STRVAL_P(str);//p2指向第一个分隔符的位置 ,找出分隔符位置主要用的是php_memnstr函数
p2 =php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);if (p2 ==NULL) {//p2为NULL表示找不到分隔符,直接返回整个字符串
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
}else{do{//将p1添加到return_value数组中 ,移动到下一个分隔符的位置
add_next_index_stringl(return_value, p1, p2 - p1, 1);
p1= p2 +Z_STRLEN_P(delim);
}while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
--limit > 1);//将最后一个值追加到return_value
if (p1 <=endp)
add_next_index_stringl(return_value, p1, endp-p1, 1);
}=
实现时调用了add_next_index_stringl将得到的每个字符串添加到数组return_value中。add_next_index_string是此功能的核心函数。
ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, intduplicate)
{
zval*tmp;
MAKE_STD_ZVAL(tmp);
ZVAL_STRINGL(tmp, str, length, duplicate);return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
}
add_next_index_stringl函数调用zend_hash_next_index_insert函数将str插入到数组中。再看看php_explode_negative_limit函数的源码
php_explode_negative_limit
//如果delimiter不在string中,且limit为负数,什么都不做,返回空的array,p2为NULL表示delimiter不在string中
if (p2 ==NULL) {/*
如果limit <= 1="" -1,那么什么都不做,因此如果只有一个字符串,那么-="" +="" (limit)="" <="0
返回空数组*/}else{int allocated = EXPLODE_ALLOC_STEP, found = 0;longi, to_return;char **positions = emalloc(allocated * sizeof(char *));//第一个单词的位置
positions[found++] =p1;do{if (found >=allocated) {
allocated= found + EXPLODE_ALLOC_STEP;/*保证有足够的内存空间*/positions= erealloc(positions, allocated*sizeof(char *));
}//positions保存每个单词的起始位置
positions[found++] = p1 = p2 +Z_STRLEN_P(delim);
}while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) !=NULL);//to_return 是return_value的数量,其实等于found - |limit|
to_return = limit +found;/*limit至少是-1,因此不需要边界检查:i永远小于found*/
for (i = 0;i < to_return;i++) { /*这个检查是检查to_return大于0*/add_next_index_stringl(return_value, positions[i],
(positions[i+1] - Z_STRLEN_P(delim)) -positions[i],1);
}
efree(positions);
}
php_explode_negative_limit也是跟php_implode类似的操作,找到分隔的字符串之后,调用add_next_index_string函数将limit + found个字符串添加到return_value数组中。
implode
string implode ( string $glue, array $pieces )
string implode ( array $pieces )
将一个一维数组的值转换为字符串
implode函数可以接收两种参数顺序。
核心代码
if (arg2 ==NULL) {//第二个参数为空,第一个参数必须为数组
if (Z_TYPE_PP(arg1) !=IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Argument must be an array");return;
}
MAKE_STD_ZVAL(delim);#define _IMPL_EMPTY ""
//默认使用""连接
ZVAL_STRINGL(delim, _IMPL_EMPTY, sizeof(_IMPL_EMPTY) - 1, 0);
SEPARATE_ZVAL(arg1);
arr= *arg1;
}else{//根据参数类型设置参数的值
if (Z_TYPE_PP(arg1) ==IS_ARRAY) {
arr= *arg1;
convert_to_string_ex(arg2);
delim= *arg2;
}else if (Z_TYPE_PP(arg2) ==IS_ARRAY) {
arr= *arg2;
convert_to_string_ex(arg1);
delim= *arg1;
}else{
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Invalid arguments passed");return;
}
}//调用php_implode函数进行转换
php_implode(delim, arr, return_value TSRMLS_CC);
在底层实现中,implode函数处理好参数之后就调用php_implode函数进行转换。
php_implode
//遍历数组的每一个元素,判断其类型,然后调用smart_str_appendl函数将值追加到字符串中
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **) &tmp, &pos) ==SUCCESS) {switch ((*tmp)->type) {caseIS_STRING:
smart_str_appendl(&implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));break;caseIS_LONG: {char stmp[MAX_LENGTH_OF_LONG + 1];
str_len= slprintf(stmp, sizeof(stmp), "%ld", Z_LVAL_PP(tmp));
smart_str_appendl(&implstr, stmp, str_len);
}break;caseIS_BOOL:if (Z_LVAL_PP(tmp) == 1) {
smart_str_appendl(&implstr, "1", sizeof("1")-1);
}break;caseIS_NULL:break;caseIS_DOUBLE: {char *stmp;
str_len= spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_PP(tmp));
smart_str_appendl(&implstr, stmp, str_len);
efree(stmp);
}break;caseIS_OBJECT: {intcopy;
zval expr;
zend_make_printable_zval(*tmp, &expr, ©);
smart_str_appendl(&implstr, Z_STRVAL(expr), Z_STRLEN(expr));if(copy) {
zval_dtor(&expr);
}
}break;default:
tmp_val= **tmp;
zval_copy_ctor(&tmp_val);
convert_to_string(&tmp_val);
smart_str_appendl(&implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
zval_dtor(&tmp_val);break;
}//添加glue字符
if (++i !=numelems) {
smart_str_appendl(&implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
}
zend_hash_move_forward_ex(Z_ARRVAL_P(arr),&pos);
}//在尾部添加字符0
smart_str_0(&implstr);
可以看到,php_implode函数遍历数组的每一个元素,判断其类型,并进行必要的类型转换,然后调用smart_str_appendl函数将值追加到字符串中。smart_str_appendl是implode实现代码中的核心函数。
smart_str_appendl
#define smart_str_appendl(dest, src, len) smart_str_appendl_ex((dest), (src), (len),0)#define smart_str_appendl_ex(dest, src, nlen, what) do { register size_t __nl;
smart_str*__dest = (smart_str *) (dest);
smart_str_alloc4(__dest, (nlen), (what), __nl);
memcpy(__dest->c + __dest->len, (src), (nlen));
__dest->len =__nl;
}while (0)
smart_str_appendl_ex主要调用memcpy函数进行字符串复制。
原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
如果本文对你有帮助,点个推荐吧,谢谢^_^。
更多PHP源码阅读文章:
[PHP源码阅读]strlen函数
[PHP源码阅读]strpos、strstr和stripos、stristr函数
www.bkjia.comtrueTechArticle[PHP源码阅读]explode和implode函数,explodeimplode explode和implode函数主要用作字符串-数组的操作,比如获取一段参数后根据某个字符分割字符串,…
php打implode 函数,[PHP源码阅读]explode和implode函数,explodeimplode_PHP教程相关推荐
- nginx源码阅读(二).初始化:main函数及ngx_init_cycle函数
前言 在分析源码时,我们可以先把握主干,然后其他部分再挨个分析就行了.接下来我们先看看nginx的main函数干了些什么. main函数 这里先介绍一些下面会遇到的变量类型: ngx_int_t: t ...
- php函数阅读,[PHP源码阅读]strtolower和strtoupper函数
字符串的操作函数中,字符串的大小写转换也算是比较常用的函数,其底层实现也比较简单,下面来一探究竟. 我在github上有对PHP源码更详细的注解.感兴趣的可以围观一下,给个star. PHP5.4源码 ...
- [PHP源码阅读]strtolower和strtoupper函数
字符串的操作函数中,字符串的大小写转换也算是比较常用的函数,其底层实现也比较简单,下面来一探究竟. 我在github上有对PHP源码更详细的注解.感兴趣的可以围观一下,给个star.PHP5.4源码注 ...
- java的resize函数_Java源码解析HashMap的resize函数
hashmap的resize函数,用于对hashmap初始化或者扩容. 首先看一下该函数的注释,如下图.从注释中可以看到,该函数的作用是初始化或者使table的size翻倍.如果table是null, ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...
- django源码阅读 manage.py文件
Django源码阅读之manager.py文件阅读 我们知道,我们运行一个django项目的时候,需要进入项目的根目录,然后输入命令,python manage.py runserver,这样,我们就 ...
- [PHP源码阅读]trim、rtrim、ltrim函数
trim系列函数是用于去除字符串中首尾的空格或其他字符.ltrim函数只去除掉字符串首部的字符,rtrim函数只去除字符串尾部的字符. 我在github有对PHP源码更详细的注解.感兴趣的可以围观一下 ...
- 阅读react-redux源码(二) - createConnect、match函数的实现
阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 上一节看了Provider组 ...
- wrappers.php,PHP源码阅读笔记六:stream_get_wrappers函数
PHP源码阅读笔记stream_get_wrappers函数 stream_get_wrappers (PHP 5) stream_get_wrappers - 返回注册的数据流列表 Descript ...
- trim函数 php,[PHP源码阅读]trim、rtrim、ltrim函数
trim系列函数是用于去除字符串中首尾的空格或其他字符.ltrim函数只去除掉字符串首部的字符,rtrim函数只去除字符串尾部的字符. 我在github有对PHP源码更详细的注解.感兴趣的可以围观一下 ...
最新文章
- SAP MM PR 审批中的REJECT
- 开源 java CMS - FreeCMS2.8 栏目页静态化参数
- 【设计模式】迪米特法则和六种原则的总结
- Python:构造函数和析构函数
- 八、深入Go 编程语言接口
- map初始化_您可曾这样初始化一个map呢?
- 【测试基础】测试用例的设计方法
- 四因素三水平正交试验表_测试用例设计方法(二)——正交实验法
- [Android自定义控件] Android自定义控件
- C++:利用泰勒公式求cos x近似值
- 数据挖掘之数据处理——SVM神经网络的数据分类预测-意大利葡萄酒种类识别
- 刷新BIOS应该做的几件事
- FZU2132 - LQX的作业(概率论)
- 网络初始化失败,点击确定后将退出
- 莫纳什大学计算机专业在哪个校区,莫纳什大学校区几个
- ios 扫码枪外设 键盘模式_想把 iPad 当笔记本电脑用?可以试试这款外接键盘
- Jmeter对Web Socket进行压力测试 —— 200人直播课实战经验
- 秋天来了,穿衣搭配。简单几件穿出独特气质
- 快速开发EasyUI Datagrid报表 thinkphp框架 ppt和视频教程
- Java生成骑缝章带有CA电子签名认证