设为首页 收藏本站
查看: 706|回复: 0

[经验分享] 再谈PHP中的str_repeat函数实现

[复制链接]

尚未签到

发表于 2017-4-1 12:22:48 | 显示全部楼层 |阅读模式
  前段时间讨论了在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则没有多余的无用空间的分配和释放操作。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-358714-1-1.html 上篇帖子: 动态创建php 类函数或函数 下篇帖子: 如何调整PHP错误报告级别
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表