trim 系列函數是用於去除字串中首尾的空格或其他字元。ltrim 函數只去除掉字串首部的字元,rtrim函數只去除字串尾部的字元。
trim
string trim ( string $str [, string $character_mask = " tnrx0B" ] )
參數說明
character_mask 預設是” tnrx0B”等空白字元。
使用..可以指定一段範圍的字元。此處要注意,”..”左右兩邊是一對合法的範圍值,如果傳遞的是非法的值會報錯。
運行樣本
先來看看用正常的使用
$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內部使用的是與運算,而不是多個的判斷條件。該部分代碼如下:
if (mode & 1) { for (i = 0; i < len; i++) { if (mask[(unsigned char)c[i]]) { trimmed++; } else { break; } } len -= trimmed; c += trimmed;}if (mode & 2) { for (i = len - 1; i >= 0; 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
一個正在努力的菜鳥 個人首頁 · 我的文章 · 9 ·