[PHP源码阅读]explode和implode函数

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为负数,则赶回空数组。

运行示例

$str = 'hello,world,heiheihei,php';

先来看看不设置limit的景象

$arr = explode(',', $str);
print_r($arr);

运行结果1

limit为正数时,limit设为1,最多重返1个要素。

$arr = explode(',', $str, 1);
print_r($arr);

运作结果2

limit为负数,limit为-1,再次回到最终的1个元素外的有着因素。

$arr = explode(',', $str, -1);
print_r($arr);

运行结果3

limit为0,当作1处理。

$arr = explode(',', $str, 0);
print_r($arr);

运作结果4

explode执行步骤

1、接收参数,处理参数为空的情形

2、创设函数中行使的一对变量

3、依据limit的值调用差其他函数分隔字符串

explode函数的主导完结是php_explode函数,上边是该函数的履行流程图:

explode流程

php_explode函数宗旨代码:

if (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);
}

源码解读

sizeof(“”) ==
0
。sizeof有二种用法,sizeof(typename)sizeof(expression),当参数为typename是,即类型名称,sizeof重回类型对应对象的大大小小;当参数为表达式时,sizeof统计表明式的归来类型对应对象的尺寸。此处,””是表明式,sizeof计算编译时编译器分配给””的长空,此时要算上\0的长短,由此是1,而strlen函数不会揣度\0

借使不安装limit,limit的默许值是LONG_MAX。在php.h文件中,LONG_MAX定义为2147483647L。

在落到实处里面,假使limit大于1,则调用php_explode函数;如果limit小于0,则调用php_explode_negative_limit函数;要是limit等于0,则被用作1处理,此时调用add_index_stringl函数将str添加到数组return_value中。

在搜寻分隔符delimiter时,调用了php_memnstr函数
php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim),
Z_STRLEN_P(delim), endp);
而php_memnstr是zend_memnstr的宏定义,zend_memnstr完成里面,因而实际是调用了C里面的memchr来查找字符delimiter。

找到分隔符的地方然后,就调用add_next_index_stringl函数将分隔获得的字符串插入到再次回到数组里。

implode

string implode ( string $glue, array $pieces )
string implode ( array $pieces )

将一个一维数组的值转换为字符串

参数表达

implode函数可以吸收三种参数顺序。其余,要是第二个参数为数组而第三个参数为空,则第四个参数为默许值”。此函数可以看做是explode的逆向进度。

当然,使用文档规定的依次可防止混淆。

运转示例

$arr = array('hello', 'world');

循序渐进文档顺序参数

$str = implode('-‘, $arr);// 输出"hello-world"

率先个参数为数组

$str = implode($arr); // 输出"helloworld"
$str = implode($arr, '-'); // 输出"hello-world"

implode执行步骤

1、接收参数并赋值
2、借使首个参数为空,则判断首个参数的门类是还是不是为数组,倘诺不是,则报错。否则,则接纳””对glue赋值,使用其用作连接符。
3、若是首个参数不为空,那么,就算第四个参数是数组类型,则将第三个参数转换成字符串类型;否则,假如第四个参数是数组类型,则将首先个参数转换成字符串类型。
4、调用php_implode函数做字符串的总是。

implode函数设置完参数之后,底层就调用php_implode函数举行字符串连接,php_implode函数的施行流程图如下:

implode流程

php_implode函数大旨代码:

// 遍历数组的每一个元素,判断其类型,然后调用smart_str_appendl函数将值追加到字符串中
    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **) &tmp, &pos) == SUCCESS) {
        switch ((*tmp)->type) {
            case IS_STRING:
                smart_str_appendl(&implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
                break;

            case IS_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;

            case IS_BOOL:
                if (Z_LVAL_PP(tmp) == 1) {
                    smart_str_appendl(&implstr, "1", sizeof("1")-1);
                }
                break;

            case IS_NULL:
                break;

            case IS_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;

            case IS_OBJECT: {
                int copy;
                zval expr;
                zend_make_printable_zval(*tmp, &expr, &copy);
                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是函数smart_str_appendl_ex的宏定义,该函数调用了memcpy做字符串的复制。

小结

暂且写这么多,还有愈来愈多的优化和PHP源码中常用的函数,将会在后来的源码阅读中国和扶桑渐讲述。

原创小说,文笔有限,才疏学浅,文中若有不正之处,万望告知。

即使本文对您有赞助,请点下推荐呢,谢谢\_

我在github有对PHP源码更详细的笺注。感兴趣的可以扫描一下,给个star。PHP5.4源码注解。能够由此commit记录查阅已添加的诠释。

相关文章