`

再谈PHP中的str_repeat函数实现

阅读更多

前段时间讨论了在PHP中生成某多个某字符或字符串的字符串的问题,呵呵。这句话听起来太别扭了。举个例子就是,生成10个a的字符串就是aaaaaaaaaa。当然这里的a可以是ab或任何其他字符串。

 

在博客“生成固定长度的某字符的字符串 PHP ”中描述了一共5中方法。也对这五种方法的效率进行了比对,其中以PHP中自带的str_repeat函数效率最优,这也在意料和情理之中。

方法4,5都是对PHP本身的函数进行了组配以实现相同的功能,虽然没有str_repeat优秀,但是其效率还是好过了方法1,和方法2.

 

方法1,2是用PHP语言自己实现的逻辑,通过字符串的迭代拼接实现的,效率当然不能和PHP中的builtin方法相提并论。

 

今天看到了PHP中的str_repeat函数的实现,仔细一看,原来和自己实现的方法1中的思路是“异曲同工”啊。那PHP中的str_repeat究竟是怎么做的呢?核心逻辑代码如下:

 

    result_len = input_len * mult;
    result = (char *)safe_emalloc(input_len, mult, 1);
    
    /* Heavy optimization for situations where input string is 1 byte long */
    if (input_len == 1) { 
        memset(result, *(input_str), mult); 
    } else {
        char *s, *e, *ee; 
        int l=0; 
        memcpy(result, input_str, input_len);
        s = result;
        e = result + input_len;
        ee = result + result_len;

        while (e<ee) {
            l = (e-s) < (ee-e) ? (e-s) : (ee-e);
            memmove(e, s, l);
            e += l;
        }
    }

    result[result_len] = '\0';

首先计算了结果字符串的长度。并分配了对应的内存空间。

然后将input_str拷贝到分配内存空间的最开始,

然后迭代将已经拷贝的内容复制到剩余的内存空间。

从代码逻辑可以看出,复制的思路不是一份一份复制的,而是复制一份、两份、四份、八份......

直到填满所分配的内存空间,然后奖内存空间的最后一位赋值为'\0'。

 

初次看到这段代码时对以下代码逻辑有不解:

 

     while (e<ee) {
            l = (e-s) < (ee-e) ? (e-s) : (ee-e);
            memmove(e, s, l);
            e += l;
        }

所分配的内存空间一定是input_str的整数倍+1。因此如果每次只是向后移一倍原始字符串长度的话,只需要在剩余长度小于原始字符串长度时退出循环,然后在将最后一位赋值为'\0'。不就可以了吗?

 

如果你也是这么想的,那么你和我刚开始犯了同样的错误。

因为,原始字符串的复制不是一份一份地进行的。如果复制7份的话(即str_repeat("abc",7);),只需要复制4次(包括第一次)。

而且最后一次复制之前剩余的未赋值的内存空间为原始字符串长度的3倍+1,即3*3+1。只需要将"abcabcabcabc"字符串中的前10个字符进行复制。这样,result_str最后一个字符必定是原始字符串的第一个字符,'a'。这个‘a’本来就是不要的。

 

索性直接:

result[result_len] = '\0';

其实就是最后字符串中那个不需要的'a'替换为字符串的结束符'\0'。

 

这样str_repeat函数就完成了。

 

****************************************************************

此外:

博客“生成固定长度的某字符的字符串 PHP ”中的方法1,虽然思想上和str_repeat一致,但是采用了字符串拼接方式,而且每次拼接都要产生新的字符串,对内存空间也是极大的浪费,如下示例:

 

如果要生成8个‘a’的字符串,首先会生成'aa',然后是‘aaaa’,然后是‘aaaaaaaa’。循环次数和str_repeat一致,但是中间生成了'aa','aaaa'两个无用字符串,而且,目标字符串越长,则垃圾越多。而且,循环中采用字符串拼接方式,效率也不高。

 

 

而str_repeat则没有多余的无用空间的分配和释放操作。

分享到:
评论

相关推荐

    PHP中的str_repeat函数在JavaScript中的实现

    PHP中有一个函数:String str_repeat($str, num);挺好用的,在 本文为大家介绍下次函数在js中的实现,感兴趣的朋友可以参考下

    php str_pad 函数用法简介

    php的str_pad()函数是把字符串填充为指定的长度,和str_repeat有类似之处,至于str_repeat的用法在此不作解释,有兴趣的可以查找手册.

    php中ob_flush函数和flush函数用法分析

    本文实例分析了php中ob_flush函数和flush函数用法。分享给大家供大家参考。具体如下: ... echo str_repeat('m0sh1' ,1000); for($i=0;$i&lt;4&gt;'; ob_flush(); flush(); sleep(1); } ?&gt; &lt;?

    php2go:使用Golang来实现PHP的常见内置函数

    PHP2Go 使用Golang来实现PHP的通用内置函数。 已经实现了约140多种功能。...str_repeat () strstr () strtr () str_shuffle () trim () ltrim () rtrim () explode () strtoupper () strtolower () chr () ord () nl2

    PHP通过内置函数memory_get_usage()获取内存使用情况

    PHP内置函数memory_get_usage()能返回当前分配给PHP脚本的内存量,单位是字节(byte)。在WEB实际开发中,这些函数非常有用,我们可以使用它来调试PHP代码性能。...$tmp = str_repeat(‘hello’, 1000);  e

    采用PHP函数memory_get_usage获取PHP内存清耗量的方法

    一,函数原型 int memory_get_usage ([ bool... $var = str_repeat(“liuhui”, 10000); echo memory_get_usage(); unset($var); echo memory_get_usage(); ?&gt; 分别输出:62328 122504 62416 说明:memory_get_usage

    PHP实现函数内修改外部变量值的方法示例

    本文实例讲述了PHP实现函数内修改外部变量值的方法。分享给大家供大家参考,具体如下: 直接上代码,如下: $a_str = 'ab'; function change_val(){ global $a_str; // 通过设置全局变量,修改变量值 //$a_str = ...

    PHP管理内存函数 memory_get_usage()使用介绍

    //143952 $tmp = str_repeat(‘http://blog.micxp.com/’, 4000); echo memory_get_usage(), ‘ ’; //232048 unset($tmp); echo memory_get_usage(); //143952 上面的程序后面的注释代表了它们的输出(单位为 ...

    PHP可逆加密/解密函数分享

    函数源码 复制代码 代码如下: function encrypt($data, $key) { $prep_code = ... $block) { $prep_code .= str_repeat(chr($pad), $pad); } $encrypt = mcrypt_encrypt(MCRYPT_DES, $key, $prep_code, MCRYPT_MOD

    PHP内存使用情况如何获取

    PHP内置函数memory_get_usage()能返回当前分配给PHP脚本的内存量,单位是字节(byte)。在WEB实际开发中,这些函数非常有用,我们可以使用它来调试PHP代码...$tmp = str_repeat('hello', 1000); echo '运行后内存:'

    解析PHP缓存函数的使用说明

     echo str_repeat(“\n”, 5000); echo $i; sleep(1); flush();}ob_start(回调函数,限定长度,随时输出缓存=’true’):开启,前提:output_buffer = onob_clear():刷新ob_end_clear():关闭,并刷新ob_flush...

    PHP实时显示输出

    //关闭缓存 //echo str_repeat(“ ”,256); //ie下 需要先发送256个字节 set_time_limit(0); for($i=0;$i”; flush(); sleep(1); } 您可能感兴趣的文章:php数组(array)输出的三种形式详解PHP学习之输出字符串...

    如何获知PHP程序占用多少内存(memory_get_usage)

    // 313864 $tmp = str_repeat(‘http://www.nowamagic.net/’, 4000); echo memory_get_usage(), ‘ ’; // 406048 unset($tmp); echo memory_get_usage(); // 313952 ?&gt; 上面的程序后面的注释代表了它们的...

    php网络开发完全手册

    7.3.1 字符串重复操作——str_repeat 104 7.3.2 字符串替换操作——str_replace 7.3.2 和str_ireplace 104 7.3.3 字符串分解操作——str_split 106 7.3.4 字符串单词数的计算函数—— 7.3.4 str_word_count 107 ...

    php中用unset销毁变量并释放内存

    $s = str_repeat('1',255); //产生由255个1组成的字符串 $m = memory_get_usage(); //获取当前占用内存 unset($s); $mm = memory_get_usage(); //unset()后再查看当前占用内存 echo $m-$mm; ?&gt; 最后输出unset()...

    xheditor-1.1.14

    2. xhEditor进阶使用 ...说明:此函数可以在插件内部或者外部Javascript代码中进行调用 showModal:显示模式窗口 参数1:模式窗口的标题title 参数2:模式窗口的内容content 参数3:模式窗口的宽度w ...

Global site tag (gtag.js) - Google Analytics