目录
strtr
源码
首页 后端开发 php教程 php中strtr函数的使用详解

php中strtr函数的使用详解

Jul 24, 2017 am 10:39 AM
php strtr 阅读

strtr

转换字符串中特定的字符,但是这个函数使用的方式多种。

echo strtr('hello world', 'hw', 'ab'); // 第一种 aello borldecho strtr('hello world', 'hw', 'a'); // 第二种 aello worldecho strtr('hello world', ['hello' => 'hi']); // 第三种 hi worldecho strtr('hello world', ['he' => 'th', 'hello' => 'hi']); // 第四种 hi world
登录后复制


时间复杂度

O(n),最差是O(n*m)

源码

以下根据每种情况逐一分析源码。
第一种、第二种,也是最常用的,但第二种,只有’h’转换成’a’,’w’没有被处理。这种方式的替换,会以短的一方为准。如果from和to其中一个是空串,会直接返回原字符串。

RETURN_STR(php_strtr_ex(str,  Z_STRVAL_P(from),  to,          MIN(Z_STRLEN_P(from), to_len)));// 从源码MIN(Z_STRLEN_P(from), to_len))可以看出来,以from、to两个字符串短的为准,剩余的会被忽略掉,所以可以解释第二种情况'w'被忽略掉
// 同理,以下to中的'b'也会被忽略掉strtr('hello world', 'h', 'ab'); // aello world
登录后复制

 

接着,我们主要看下php_strtr_ex方法,是怎么实现字符转换。源码是使用hash表实现,hash表把from的每个字符,一一对应为to的相应位置的字符。

static zend_string *php_strtr_ex(zend_string *str, char *str_from, char *str_to, size_t trlen)
{// trlen的值就是MIN(Z_STRLEN_P(from), to_len))
    // 先构建一个hash表,用php伪代码来解释第一种情况构建好的hash表
    // array('g'=>'g','h'=>'a','i'=>'i','w'=>'b')unsigned char xlat[256], j = 0;do { xlat[j] = j; } while (++j != 256);for (i = 0; i < trlen; i++) {
        xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
    }    // 接着遍历字符串,从hash表中找到转换的字符for (i = 0; i < ZSTR_LEN(str); i++) {if (ZSTR_VAL(str)[i] != xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]]) {
            new_str = zend_string_alloc(ZSTR_LEN(str), 0);
            memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);// 从hash表中找到转换的字符ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];break;
        }
    }for (;i < ZSTR_LEN(str); i++) {// 从hash表中找到转换的字符ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
    }
}
登录后复制


第三种、第四种from是个数组,如果from是数组,情况就不是一对一的字符转换,是字符串对字符串的转换了,把key整个字符串转换成value字符串。

第三种,from数组只有一对键值对,实现思路是,根据kmp算法在主串中搜索key(被替换的字符串)的位置,如果找到,就使用value替换掉。kmp本身的效率是O(n),所以如果字符串内进行了m次替换,这种情况下strtr效率会是O(n*m)

// 搜索被替换的字符串的所有位置e = s = ZSTR_VAL(new_str);end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);// php_memnstr搜索 被替换的字符串 的所有位置,并替换掉for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    memcpy(e, p, r - p);
    e += r - p;
    memcpy(e, str, str_len);
    e += str_len;
    (*replace_count)++;
}
登录后复制

第四种,通过数组替换多个字符串,这种是各种情况效率最差的

// 先构造所有 被替换的字符串ZEND_HASH_FOREACH_STR_KEY(pats, str_key) {
    len = ZSTR_LEN(str_key);// 计算所有 被替换的字符串 最长和最短值if (len > maxlen) {
        maxlen = len;
    }if (len < minlen) {
        minlen = len;
    }// 记录每个key长度值的hash值num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));// 记录每个key首字符的hash值bitset[((unsigned char)ZSTR_VAL(str_key)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(str_key)[0]) % sizeof(zend_ulong));
    
} ZEND_HASH_FOREACH_END();// 辅助两个hash表,替换的字符串old_pos = pos = 0;while (pos <= slen - minlen) {key = str + pos;// 如果从首字符的hash表匹配到,表示以key[0]字符开头的有可能是被替换的字符串if (bitset[((unsigned char)key[0]) / sizeof(zend_ulong)] & (Z_UL(1) << (((unsigned char)key[0]) % sizeof(zend_ulong)))) {
        len = maxlen;if (len > slen - pos) {
            len = slen - pos;
        }// key从maxlen循环到minlen,所以,第四种'hello'和'he',最先匹配到hellowhile (len >= minlen) {// 如果从长度hash表里面匹配到被替换的字符串里可能的长度,就从from数组里面找到替换的键值对zend_hash_str_findif ((num_bitset[len / sizeof(zend_ulong)] & (Z_UL(1) << (len % sizeof(zend_ulong))))) {
                entry = zend_hash_str_find(pats, key, len);if (entry != NULL) {
                    zend_string *s = zval_get_string(entry);
                    smart_str_appendl(&result, str + old_pos, pos - old_pos);
                    smart_str_append(&result, s);
                    old_pos = pos + len;pos = old_pos - 1;
                    zend_string_release(s);break;
                }
            }
            len--;
        }
    }pos++;
}
登录后复制

这种情况有点复杂,下面的php伪代码翻译一下以上的C语言代码

$bitset = array_fill(0, 255, 0); // 首字符的hash表$num_bitset = array_fill(0, 255, 0); 
// key长度值的hash值$min_len = PHP_INT_MAX;$max_len = 0;$len = 0;
// echo strtr(&#39;hello world&#39;, [&#39;he&#39; => 'th', 'hello' => 'hi']);
$pats = ['he', 'hello'];
foreach($pats as $v){$len = strlen($v);if($len > $max_len) {$max_len = $len;
    }
    if($len < $min_len) {$min_len = $len;
    }
    $num_bitset[intdiv($len,8)] |= 1 << ($len%8);$bitset[intdiv(ord($v[0]),8)] |= 1 << (ord($v[0])%8);
}// print_r(array_unique($num_bitset));
// print_r(array_unique($bitset));
// 例如我们匹配hello,首字符是h,长度5
// 以下两行就是以上C语言的while循环里面两个if判断echo $bitset[intdiv(ord('h'),8)] & 1 << (ord('h')%8),PHP_EOL;echo $num_bitset[intdiv(5,8)] & 1 << (5%8),PHP_EOL;
登录后复制

以上是php中strtr函数的使用详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CakePHP 项目配置 CakePHP 项目配置 Sep 10, 2024 pm 05:25 PM

在本章中,我们将了解CakePHP中的环境变量、常规配置、数据库配置和电子邮件配置。

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

CakePHP 路由 CakePHP 路由 Sep 10, 2024 pm 05:25 PM

在本章中,我们将学习以下与路由相关的主题?

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

See all articles