This article mainly introduces the explanation of some strange behaviors of strtr function in PHP. It has certain reference value. Now I share it with you. Friends in need can refer to it.
Some strange behaviors of strtr function in PHP Explanation of behavior
A few days ago, a buddy sent me an article to read, saying that the strtr function has some strange behaviors
Looking at the source code of PHP, I got the following explanation:
[Strange Behavior 1]
Let’s first look at the two states of this php string replacement function strtr()
strtr(string,from,to)
or strtr(string,array )
First of all, for the first method of strtr function
Let’s take a look at the following example:
echo strtr("I Love you","Lo","lO");
The result obtained is
I lOve yOu
This result reminds us
1.strtr It is case-sensitive
[Source Code Analysis 1]
The final implementation function of the strtr function is the php_strtr function in line 2670 of the string.c file. Its source code is as follows:
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;}
The entire function performs hash replacement on 256 characters. Of course, these 256 characters include uppercase and lowercase letters.
[Strange Behavior 2]
2.strtr Replacement is very special. Please look at the yOu at the back. The O in the middle is replaced. This is obviously not our intention.
[Source Code Analysis 2]
The same principle is as above, it is for each The corresponding replacement of characters is based on characters, so the replacement is characters, not strings
[Strange Behavior Three]
Give another special example to illustrate this php sttr function The weird
echo strtr("I Love you","Love","");
result is
I Love you
Nothing will change, so strtr needs to pay attention to: it cannot be replaced with empty, which is the last one The parameter cannot be an empty string, of course spaces are allowed.
[Source code analysis three]
In line 2833 of the string.c file, we can see that the calling program is as follows:
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)) is the smallest of the lengths of the two strings from and to. In the case shown in three, the result is 0. From the php_strtr function we can see that
if ((trlen < 1) || (len < 1)) {return str;}
When the length is less than 1 Returns the original string. so. . . .
[Strange Behavior 4]
Another example of another case of strtr function
echo strtr("I Loves you","Love","lOvEA");
The result is
I lOvEs yOu
Pay attention to the A in the third parameter. It does not appear in the result.
[Source code analysis three]
The reason is similar to the second one. MIN(Z_STRLEN_PP(from), Z_STRLEN_PP(to)) takes both from and to. The smallest length among the strings
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);}
The above is the entire content of this article. I hope it will be helpful to everyone's learning. For more related content, please pay attention to the PHP Chinese website!
Related recommendations:
About the analysis of HashTable in PHP source code
About the analysis of Zend HashTable in PHP source code
The above is the detailed content of An explanation of some strange behaviors of the strtr function in PHP. For more information, please follow other related articles on the PHP Chinese website!