首頁  >  文章  >  後端開發  >  關於PHP中strtr函數一些奇怪行為的解釋

關於PHP中strtr函數一些奇怪行為的解釋

不言
不言原創
2018-06-28 16:19:201528瀏覽

這篇文章主要介紹了關於PHP中strtr函數一些奇怪行為的解釋,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

PHP中strtr函數一些奇怪行為的解釋

前些日子,一哥們給我發了篇文章給我看,說是strtr函數有一些奇怪的行為

查看PHP的源碼,得到如下解釋:

【奇怪行為一】
先來看看這個php字串替換函數strtr()的兩個狀態
strtr(string,from,to)
或strtr(string,array )
首先針對strtr函數第一種方式
我們看看下面的舉例:

   echo strtr("I Love you","Lo","lO");

得到的結果是
I lOve yOu

這個結果提醒我們

1.strtr它是區分大小寫的

【原始碼分析一】
strtr函數的最終實作函數是string.c檔案的2670行的php_strtr函數,其原始碼如下:

   PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen){int i;unsigned char xlat[256]; 
 if ((trlen < 1) || (len < 1)) {return str;} 
 for (i = 0; i < 256; xlat[i] = i, i++); 
 for (i = 0; i < trlen; i++) {xlat[(unsigned char) str_from[i]] = str_to[i];} 
 for (i = 0; i < len; i++) {str[i] = xlat[(unsigned char) str[i]];} 
 return str;}

整個函數是對於256個字元進行hash替換,這256個字元當然包括大小寫字母啦

【奇怪行為二】

2.strtr的替換是很特殊的,你注意看後面那個yOu,中間的O被替換的,這顯然不是我們的本意

【源碼分析二】

道理同上,它是對每個字符進行對應替換,是以字符為單位,所以替換的是字符,而不是字符串

【奇怪行為三】

再舉一個特殊例子,說明這個php sttr函數的怪異

   echo strtr("I Love you","Love","");

結果是

I Love you

什麼也不會改變,所以strtr需要注意的是:不能被替換為空,也就是末位那個參數不能是空字串,當然空格是可以的。

【原始碼分析三】

在string.c檔案的2833行,我們可以看到其呼叫程式如下:

   php_strtr(Z_STRVAL_P(return_value),
 Z_STRLEN_P(return_value),
 Z_STRVAL_PP(from),
 Z_STRVAL_PP(to),
 MIN(Z_STRLEN_PP(from), 
 Z_STRLEN_PP(to)));

MIN(Z_STRLEN_PP(from), Z_STRLEN_PP (to))是取from和to兩個字串的長度中最小的,如三所示的情況,其結果為0,從php_strtr函數中我們可以看到

if ((trlen < 1) || (len < 1)) {return str;}

當長度小於1時傳回原來的字串。所以。 。 。 。

【奇怪行為四】

再次舉例strtr函數的另一個情況

 echo strtr("I Loves you","Love","lOvEA");

結果是

I lOvEs yOu

#注意第三個參數的A,在結果中並沒有出現
【源碼分析三】
其理由與二類似,MIN(Z_STRLEN_PP(from), Z_STRLEN_PP(to))是取from和to兩個字串的長度中最小的

  static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *hash){
  zval **entry;char  *string_key;
  uint   string_key_len;zval **trans;
  zval   ctmp;ulong num_key;
  int minlen = 128*1024;
  int maxlen = 0, pos, len, found;
  char *key;
  HashPosition hpos;smart_str result = {0};
  HashTable tmp_hash;zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0);
  zend_hash_internal_pointer_reset_ex(hash, &hpos);
  while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) {
  switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) {
  case HASH_KEY_IS_STRING:len = string_key_len-1;
  if (len < 1) {
  zend_hash_destroy(&tmp_hash);
  RETURN_FALSE;
  }
  zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL);
  if (len > maxlen) {maxlen = len;}
  if (len < minlen) {minlen = len;}break; 
  case HASH_KEY_IS_LONG:Z_TYPE(ctmp) = IS_LONG;Z_LVAL(ctmp) = num_key;
  convert_to_string(&ctmp);len = Z_STRLEN(ctmp);
  zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL);
  zval_dtor(&ctmp); 
 if (len > maxlen) {
 maxlen = len;}
 if (len < minlen) {
 minlen = len;}break;}
 zend_hash_move_forward_ex(hash, &hpos);} 
 key = emalloc(maxlen+1);pos = 0; 
 while (pos < slen) {
 if ((pos + maxlen) > slen) {maxlen = slen - pos;} 
 
found = 0;memcpy(key, str+pos, maxlen); 
 for (len = maxlen; len >= minlen; len--) {
 key[len] = 0;
 if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
 char *tval;
 int tlen;zval tmp; 
 if (Z_TYPE_PP(trans) != IS_STRING) {
 tmp = **trans;zval_copy_ctor(&tmp);convert_to_string(&tmp);
 tval = Z_STRVAL(tmp);tlen = Z_STRLEN(tmp);
 } else {tval = Z_STRVAL_PP(trans);
 tlen = Z_STRLEN_PP(trans);} 
 
smart_str_appendl(&result, tval, tlen);pos += len;found = 1; 
 if (Z_TYPE_PP(trans) != IS_STRING) {zval_dtor(&tmp);}break;} } 
 if (! found) {smart_str_appendc(&result, str[pos++]);}} 
 
efree(key);zend_hash_destroy(&tmp_hash);smart_str_0(&result);
RETVAL_STRINGL(result.c, result.len, 0);}

   以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:

關於PHP原始碼中HashTable的解析

#關於PHP原始程式碼中Zend HashTable的解析

#

以上是關於PHP中strtr函數一些奇怪行為的解釋的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:php註冊樹詳解下一篇:php註冊樹詳解