特定の文字または文字列に基づいて配列を配列に分割する必要がある場合、explode は非常に便利に使用できますが、~explode の仕組みをご存知ですか~~
まず第一に、explode がスペースも割り当てることは確実です。間違いない。
#define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
....
/ /_estrndup の実装: zend/zend_alloc.c
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC; ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) {
return p;
}
memcpy(p, s, length); // スペースを確保
p[length] = 0;
// , substr と strrchr strstr で使用される ZVAL_STRING も使用されます アピールの実装
以下は、explode の 3 番目のパラメータ制限に基づいて呼び出しを分析するものです: 条件は、explode の最後の 3 行に対応します。制限条件
注: 制限がデフォルトになっている (渡されていない) 場合、そのデフォルト値は LONG_MAX であり、これはブランチ 1 の場合です
1、limit > 1:
ext/standard にもある php_explode メソッドを呼び出します/string.c で、explode が表示されるすぐ上に実装されています (この関数でこのファイルからメソッドを検索するときに非常に便利です。ほとんどすべてのメソッドが関数のすぐ上にあります^_^)。
をコピーします。コード
コードは次のとおりです:
PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
{
char *p1, *p2, *endp;
//最初に取得するのは、 source string
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
//レコード開始位置
p1 = Z_STRVAL_P(str); 以下は str 内の区切り文字の位置を取得するものです。 strrpos と strpos にもあります。このメソッドは
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); を見つけるために使用されます。 、explore( '|', 'abc'); を呼び出すと、結果は array(0 => 'abc')
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1); になります。 else {
//次の区切り文字の位置を最後まで取得するシーケンスループ
do {
//取得される部分文字列(前の位置からこの位置までの中間部分、前の位置が初めて始まります
add_next_index_stringl(return_value, p1 , p2 - p1, 1);
//区切り文字の位置 p2 + 区切り文字の長さを見つけます
//たとえば、区切り文字 = '|'、元の文字列 = 'ab |c'、p2 = 2、p1=2+1=3
p1 = p2 + Z_STRLEN_P(delim)
} while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
--limit > ;
//最後の区切り文字の後の文字列を結果の array
//explode('|', 'avc|sdf'); > 'avc' , 1= >
コードをコピーします
コードは次のとおりです:
PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, long limit)
{
# EXPLODE_ALLOC_STEP 64 を定義します
char *p1, *p2, * endp ;
p1 = Z_STRVAL_P(str);
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim); Z_STRLEN_P(delim), endp); if (p2 = = NULL) { //ここで処理されない場合、explore('|', 'abc', -1) は不正となり、値を取得できません/* limit <= -1 なので何もしません。したがって、チャンクが 1 つだけの場合 - 1 + (limit) <= 0
何もしないと空の配列が返されます
*/
} else {
int assign = EXPLODE_ALLOC_STEP, found = 0 ;
long i, to_return;
char * *positions = emalloc(allocated * sizeof(char *));
//この配列は、すべての部分文字列の読み取り位置を保存するために使用されます。 [found++] = p1; //もちろん、開始位置を保存する必要があります
//次の 2 つのループ、最初のループは、文字列内に出現するすべての区切り文字の位置をループし、次の部分文字列の読み取り位置を保存します
do {
if (found >=割り当てられました) {
allocated = found + EXPLODE_ALLOC_STEP;/* 十分なメモリがあることを確認します */
positions = erealloc(positions, allowed*sizeof(char *));
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 = limit + found;
/* 限界は少なくとも -1 であるため、境界チェックの必要はありません : i は常に found より小さくなります */
for (i = 0) ;i < to_return;i++) { /* これは to_return > 0 もチェックします */
add_next_index_stringl(return_value, 位置[i],
(位置[i+1] - Z_STRLEN_P(delim)) - 位置[i] ,
1
);
}
efree(positions);//非常に重要です、メモリを解放します
}
#undef EXPLODE_ALLOC_STEP
}
3. 最初と 2 番目の条件がすべて満たされている場合満たされていない場合は、Return array(0 => 'avc|sd'); のこのブランチを入力します。
コードをコピー
コードは次のとおりです:
//add_index_stringl ソース コード
//ファイル 4: zend/zend_API.c
ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int dedicated) /* {{{ */
{
MAKE_STD_ZVAL(tmp);
ZVAL_STRINGL(tmp, str、長さ、重複);
return zend_hash_next_index_insert( Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
//zend_hash_next_index_insert
//zend/zend_hash.h
#define zend_hash_next_index_insert (ht、pData、 nDataSize, pDest)
_zend_hash_index_ update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
//zend/zend_hash.c ///長すぎます~~~~もう投稿しませんそれはわかります(割り当てられたスペースを除く)、
limit>1の場合、効率はO(N) [Nは限界値]、
limitlimit=1 または limit=0 の場合、効率は O(1)
http://www.bkjia.com/PHPjc/324052.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/324052.html技術記事特定の文字または文字列に基づいて配列を配列に分割する必要がある場合、explode を使用すると非常に便利ですが、知っていますか~explode の仕組み~~ まず最初に、確信してください...