trim系列函数是用于去除字符串中首尾的空格或其他字符。ltrim函数只去除掉字符串首部的字符,rtrim函数只去除字符串尾部的字符。

我在github有对PHP源码更详细的注解。感兴趣的可以围观一下,给个star。PHP5.4源码注解。可以通过commit记录查看已添加的注解。

trim

string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )

参数说明

character_mask
默认是" \t\n\r\0\x0B"等空白字符。

使用..可以指定一段范围的字符。此处要注意,".."左右两边是一对合法的范围值,如果传递的是非法的值会报错。

运行示例

先来看看用正常的使用:

$str = 'hello..';
$new_str = trim($str, '.'); // 结果是hello

一个比较诡异的结果。这里报错是因为php把..左右两边看作是范围值,而此处'..'左边是字符'.',PHP内部将认为其是一个缺少右边界的范围值。

$str = 'hello...';$second_str = trim($str, '...'); // 报错

第二个参数使用合法的边界值:

$str = 'helloabcdefg';
$new_str = trim($str, 'a..g'); // 输出hello

trim执行步骤

trim、ltrim、rtrim三个函数都是调用了php_do_trim函数,区别在于第二个参数mode的不同。本文主要对trim函数进行分析,ltrim和rtrim函数跟trim的类似。然后php_do_trim会调用了php_trim来实现功能,因此trim函数的核心函数时php_trim函数。其执行步骤如下:

1、根据what的值设置保存过滤字符的mask数组

2、过滤在字符串首部的待过滤字符

3、过滤在字符串尾部的待过滤字符

php_trim函数执行的流程图如下:

源码解读

php_trim函数先调用了php_charmask,这个函数试将过滤字符设置为mask[char] = 1的形式,这样就是一个哈希数组,然后可用于后面的判断。如果第二个参数是范围值时,调用了memset函数给mask数组赋值。

在用mode变量判断是哪种过滤时,此处有一个小优化,在PHP内部使用的是与运算,而不是多个的判断条件。该部分代码如下:

    ) {
        ; i < len; i++) {
            if (mask[(unsigned char)c[i]]) {
                trimmed++;
            } else {
                break;
            }
        }
        len -= trimmed;
        c += trimmed;
    }
    ) {
        ; i >= ; i--) {
            if (mask[(unsigned char)c[i]]) {
                len--;
            } else {
                break;
            }
        }
    }

判断的过程:

1 && 1 == 1 左边需要过滤
2 && 1 == 0 左边不需要过滤
3 && 1 == 1 左边需要过滤
1 && 2 == 0 右边不需要过滤
2 && 2 == 1 右边需要过滤
3 && 2 == 1 右边需要过滤

像这样使用位操作可以提高程序的效率,而且代码更加简洁易读。

小结

阅读这个函数的源码,首先学习到在C语言中,如果需要做键值对数组,而且键值是单个字符,可以使用unsigned char的类型做数组下标,这样可以构造类似字符作为下标的映射数组。

第二个就是使用位运算可以提高程序效率和代码可读性。

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

如果本文对你有帮助,请点下推荐吧,谢谢^_^

最后再安利一下,我在github有对PHP源码更详细的注解。感兴趣的可以围观一下,给个star。PHP5.4源码注解。可以通过commit记录查看已添加的注解。

更多源码文章,欢迎访问个人主页继续查阅:hoohack

[PHP源码阅读]trim、rtrim、ltrim函数的更多相关文章

  1. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

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

    explode和implode函数主要用作字符串和数组间转换的操作,比如获取一段参数后根据某个字符分割字符串,或者将一个数组的结果使用一个字符合并成一个字符串输出.在PHP中经常会用到这两个函数,因此 ...

  3. [PHP源码阅读]array_pop和array_shift函数

    上篇文章介绍了PHP添加元素到数组的函数,那么当然有从数组中删除元素.array_pop和array_shift只从数组的头或尾删除一个元素.经过阅读源码,发现这两个函数的实现都是调用了同一个函数-- ...

  4. [PHP源码阅读]array_push和array_unshift函数

    在PHP中,在数组中添加元素也是一种很常用的操作,分别有在数组尾部和头部添加元素,看看PHP内部是如何实现数组插入的操作. 我在github有对PHP源码更详细的注解.感兴趣的可以围观一下,给个sta ...

  5. [PHP源码阅读]empty和isset函数

    近日被问到PHP中empty和isset函数时怎么判断变量的,刚开始我是一脸懵逼的,因为我自己也只是一知半解,为了弄懂其真正的原理,赶紧翻开源码研究研究.经过分析可发现两个函数调用的都是同一个函数,因 ...

  6. PHP源码阅读(一):str_split函数

    注:源码版本:php5.6.33. 函数简介 str_split 原型: array str_split ( string $string [, int $split_length = 1 ] ) 说 ...

  7. [PHP源码阅读]array_slice和array_splice函数

    array_slice和array_splice函数是用在取出数组的一段切片,array_splice还有用新的切片替换原删除切片位置的功能.类似javascript中的Array.prototype ...

  8. [PHP源码阅读]strtolower和strtoupper函数

    字符串的操作函数中,字符串的大小写转换也算是比较常用的函数,其底层实现也比较简单,下面来一探究竟. 我在github上有对PHP源码更详细的注解.感兴趣的可以围观一下,给个star.PHP5.4源码注 ...

  9. ONNX Runtime 源码阅读:Graph::SetGraphInputsOutputs() 函数

    目录 前言 正文 总结 前言 为了深入理解ONNX Runtime的底层机制,本文将对 Graph::SetGraphInputsOutputs() 的代码逐行分析. 正文 首先判断Graph是否从O ...

随机推荐

  1. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  2. Sublime Text3安装JsHint

    介绍 Sublime Text3使用jshint依赖Nodejs,SublimeLinter和Sublimelinter-jshint. NodeJs的安装省略. 安装SublimeLinter Su ...

  3. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  4. excel 日期/数字格式不生效需要但双击才会生效的解决办法

    原因: Excel2007设置过单元格格式后,并不能立即生效必须挨个双击单元格,才能生效.数据行很多.效率太低. 原因:主要是一些从网上拷贝过来的日期或数字excel默认为文本格式或特殊-中文数字格式 ...

  5. CRL快速开发框架系列教程十二(MongoDB支持)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  6. dagger2系列之Scope

    Dagger的Scope注解代表的是作用域,通过实现自定义@Scope注解,标记当前生成对象的使用范围,标识一个类型的注射器只实例化一次,在同一个作用域内,只会生成一个实例, 然后在此作用域内共用一个 ...

  7. BlockingCollection使用

    BlockingCollection是一个线程安全的生产者-消费者集合. 代码 public class BlockingTest { BlockingCollection<int> bc ...

  8. Java获取本机的IP与MAC地址

    有些机器有许多虚拟的网卡,获取IP地址时会出现一些意外,所以需要一些验证: // 获取mac地址 public static String getMacAddress() { try { Enumer ...

  9. dedecms 后台栏目添加图片

    前台调用栏目时需要显示图标,整理一下: 第一步:“系统->SQL命令工具” , 插入sql语句 alter table dede_arctype add typeimg varchar() 第二 ...

  10. MySQL 数据库双向同步复制

    MySQL 复制问题的最后一篇,关于双向同步复制架构设计的一些设计要点与制约. 问题和制约 数据库的双主双写并双向同步场景,主要考虑数据完整性.一致性和避免冲突.对于同一个库,同一张表,同一个记录中的 ...