PHP 原始碼探秘 為什麼 trim 會導致亂碼

2021-09-16 12:17:08 字數 3800 閱讀 5293

我的部落格

執行以下**:

$tag = "網際網路產品、";

$text = rtrim($tag, "、");

print_r($text);

我們可能以為會得到的結果是網際網路產品,實際結果是網際網路產�。為什麼會這樣呢?

php 裡使用mb_字首的都是多位元組函式

比如

$str = "abcd";

print_r(strlen($str)."\n"); // 4

print_r(mb_strlen($str)."\n"); // 4

$str = "周夢康";

print_r(strlen($str)."\n"); // 9

print_r(mb_strlen($str)."\n"); // 3

mb_系列函式是以「多個位元組組成的乙個字元」為顆粒度來操作的,不帶mb_則是按實際的位元組數來操作的。

trim函式文件

string trim ( string $str [, string $character_mask = " \t\n\r\0\x0b" ] )
該函式不是多位元組函式,也就是說,漢字這樣的多位元組字元,會拿其頭或尾的單位元組來和後面的$character_mask對應的char陣列進行匹配,如果在後面的陣列中,則刪掉,繼續匹配。比如:

echo ltrim("bcdf","abc"); // df
如下面的 demo 中的函式string_print_char所示:

0xe3 0x80 0x81三位元組組成,

0xe5 0x93 0x81三位元組組成。

所以在執行rtrim的時候,通過位元組比對,會將0x81去掉,導致了最後出現了亂碼。

檢視 php7 的原始碼,然後提煉出下面的小 demo ,方便大家一起學習,其實php原始碼的學習並不難,每天進步一點點。

//

// main.c

// trim

//// created by 周夢康 on 2017/10/18.

//#include #include #include void string_print_char(char *str);

void php_charmask(unsigned char *input, size_t len, char *mask);

char *ltrim(char *str,char *character_mask);

char *rtrim(char *str,char *character_mask);

int main(int argc, char const *ar**)

char *ltrim(char *str,char *character_mask)

else

}len -= trimmed;

str += trimmed;

res = (char *) malloc(sizeof(char) * (len+1));

memcpy(res,str,len);

return res;

}char *rtrim(char *str,char *character_mask)

else

} while (i-- != 0);

}res = (char *) malloc(sizeof(char) * (len+1));

memcpy(res,str,len);

return res;

}void string_print_char(char *str)

printf("\n");

}void php_charmask(unsigned char *input, size_t len, char *mask)

}

如果覺得 demo 還不夠清晰的,複製下來,自己執行一次吧~

c 語言基礎較差的同學也不用擔心,我準備後面專門寫乙個php小白學習 c 語言的系列入門短文哈。

那麼我們就依葫蘆畫瓢,用 php 本身的多位元組函式來實現下吧:

function mb_rtrim($string, $trim, $encoding)

$len = mb_strlen($string, $encoding);

if ($len > 0) else

} while ($i-- != 0);

}return mb_substr($string, 0, $len, $encoding);

}mb_internal_encoding("utf-8");

$tag = "網際網路產品、";

$encoding = mb_internal_encoding();

print_r(mb_rtrim($tag, "、",$encoding));

當然你也可以使用正則來做。通過上面的函式學習,單位元組函式和多位元組函式,你學會了嗎?

php_function(trim)

php_function(rtrim)

php_function(ltrim)

static void php_do_trim(internal_function_parameters, int mode)

phpapi zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)

else

}len -= trimmed;

c += trimmed;

}if (mode & 2) else

} while (i-- != 0);}}

} else else

}len -= trimmed;

c += trimmed;

}if (mode & 2) else

} while (i-- != 0);}}

}} else else

}len -= trimmed;

c += trimmed;

}if (mode & 2) else

} while (i-- != 0);}}

}if (zstr_len(str) == len) else

}

/*  else if ((input+1 < end) && input[0] == '.' && input[1] == '.') 

if (input+2 >= end)

if (input[-1] > input[2])

/* fixme: better error (a..b..c is the only left possibility?) */

php_error_docref(null, e_warning, "invalid '..'-range");

result = failure;

continue;

} else

}return result;

}/* }}} */

PHP 原始碼探秘 為什麼 trim 會導致亂碼

我的部落格 執行以下 tag 網際網路產品 text rtrim tag,print r text 我們可能以為會得到的結果是網際網路產品,實際結果是網際網路產 為什麼會這樣呢?php 裡使用mb 字首的都是多位元組函式 比如 str abcd print r strlen str n 4 prin...

Mybatis原始碼分析 trim標籤

在第乙個trim標籤中,存在prefix屬性,那麼語句拼湊為 where id 檢查suffix和suffixoverrides,suffixoverrides值為空,那麼不做任何處理,此時會繼續拼接suffix的值,所以sql語句變成where id and 在第二個trim標籤中,存在 pref...

php原始碼是什麼

php原始碼是什麼?php原始碼指的就是php源 源 是用特定程式語言編寫的人類可讀文字,源 的目標是為可以轉換為機器語言的計算機設定準確的規則和規範。因此,源 是程式和 的基礎。php即 超文字預處理器 是一種通用開源指令碼語言。php是在伺服器端執行的指令碼語言,與c語言類似,是常用的 程式語言...