【PHP源碼閱讀】explode和implode函數,explodeimplode_PHP教程

來源:互聯網
上載者:User

【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為負數,則返回空數組。

運行樣本

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

先來看看不設定limit的情況

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

limit為正數時,limit設為1,最多返回1個元素。

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

limit為負數,limit為-1,返回最後的1個元素外的所有元素。

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

limit為0,當作1處理。

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

explode執行步驟

1、接收參數,處理參數為空白的情況

2、建立函數中使用的局部變數

3、根據limit的值調用不同的函數分隔字串

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函數的執行流程圖如下:

// 遍曆數組的每一個元素,判斷其類型,然後調用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源碼註解。

http://www.bkjia.com/PHPjc/1128118.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1128118.htmlTechArticle【PHP源碼閱讀】explode和implode函數,explodeimplode explode和implode函數主要用作字串和數組間轉換的操作,比如擷取一段參數後根據某個字元分...

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.