[PHP源码阅读]strpos、strstr和stripos、stristr函数,strposstristr_PHP教程
[PHP源码阅读]strpos、strstr和stripos、stristr函数,strposstristr
strpos
<span>mixed</span> <span>strpos</span> ( <span>string</span> <span>$haystack</span>, <span>mixed</span> <span>$needle</span> [, int <span>$offset</span> = 0 ] )
如果offset指定了,查找会从offset的位置开始。offset不能为负数。
返回needle第一次出现在haystack的位置。如果在haystack中找不到needle,则返回FALSE。
needle,如果needle不是字符串,它会被转换成整型数值并赋值为该数值的ASCII字符。请看下面例子。
例子
<span>$str</span> = "hello"<span>; </span><span>$pos</span> = <span>strpos</span>(<span>$str</span>, 111<span>); </span><span>//</span><span> 111的ASCII值是o,因此$pos = 4</span>
strpos核心源码
<span>if</span> (Z_TYPE_P(needle) ==<span> IS_STRING) { </span><span>if</span> (!<span>Z_STRLEN_P(needle)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, </span><span>"</span><span>Empty needle</span><span>"</span><span>); RETURN_FALSE; } </span><span>//</span><span> 调用php_memnstr函数查找needle</span> found = php_memnstr(haystack +<span> offset, Z_STRVAL_P(needle), Z_STRLEN_P(needle), haystack </span>+<span> haystack_len); } </span><span>else</span><span> { </span><span>//</span><span> 如果不是字符串,转换成数字并赋值为该数字的ASCII字符。</span> <span>if</span> (php_needle_char(needle, needle_char TSRMLS_CC) !=<span> SUCCESS) { RETURN_FALSE; } </span><span>//</span><span>设置结束字符</span> needle_char[<span>1</span>] = <span>0</span><span>; found </span>= php_memnstr(haystack +<span> offset, needle_char, </span><span>1</span><span>, haystack </span>+<span> haystack_len);<br /> } }</span>
有一点要注意的是,如果needle不是字符串的话,会调用php_needle_char函数将needle转成整型数字并转换为其ASCII值。
查找函数
函数最后返回的是found,php_memnstr函数实现了查找的方法。那么再继续看看php_memnstr函数做了什么:
<span>#define</span> php_memnstr zend_memnstr
php_memnstr是函数zend_memnstr的宏定义,查看zend_memnstr函数如下:
<span>static</span> inline <span>char</span> *<span> zend_memnstr(</span><span>char</span> *haystack, <span>char</span> *needle, <span>int</span> needle_len, <span>char</span> *<span>end) { </span><span>char</span> *p =<span> haystack; </span><span>char</span> ne = needle[needle_len-<span>1</span><span>]; </span><span>if</span> (needle_len == <span>1</span><span>) { </span><span>return</span> (<span>char</span> *)memchr(p, *needle, (end-<span>p)); } </span><span>if</span> (needle_len > end-<span>haystack) { </span><span>return</span><span> NULL; } </span><span>//</span><span> 第一个优化,只查找end - needle_len次</span> end -=<span> needle_len; </span><span>while</span> (p <=<span> end) { </span><span>//</span><span> 第二个优化,先判断字符串的开头和结尾是否一样再判断整个字符串</span> <span>if</span> ((p = (<span>char</span> *)memchr(p, *needle, (end-p+<span>1</span>))) && ne == p[needle_len-<span>1</span><span>]) { </span><span>if</span> (!memcmp(needle, p, needle_len-<span>1</span><span>)) { </span><span>return</span><span> p; } } </span><span>if</span> (p ==<span> NULL) { </span><span>return</span><span> NULL; } p</span>++<span>; } </span><span>return</span><span> NULL; }</span>
第一个优化,因为(char *)memchr(p, *needle, (end-p+1)是在end - needle_len + 1(即haystack_len+1)中查找,如果p为空,说明needle的第一个字符在p中从未出现过。
strstr
<span>string</span> <span>strstr</span> ( <span>string</span> <span>$haystack</span>, <span>mixed</span> <span>$needle</span> [, bool <span>$before_needle</span> = <span>false</span> ] )
返回needle在haystack中第一次出现的位置到结束的字符串。
这个函数的区分大小写的。
如果needle在haystack中不存在,返回FALSE。
如果before_needle为true,则返回haystack中needle在haystack第一次出现的位置之前的字符串。
strstr核心源码
<span>if</span><span> (found) { </span><span>//</span><span> 计算出found的位置</span> found_offset = found -<span> haystack; </span><span>if</span><span> (part) { RETURN_STRINGL(haystack, found_offset, </span><span>1</span><span>); } </span><span>else</span><span> { RETURN_STRINGL(found, haystack_len </span>- found_offset, <span>1</span><span>); } }</span>
strstr函数的前半部分跟strpos类似,区别在于strstr函数在找到位置后,需要返回haystack部分的字符串。part变量就是调用strstr函数时传递的before_needle变量。
stripos
<span>mixed</span> <span>stripos</span> ( <span>string</span> <span>$haystack</span>, <span>string</span> <span>$needle</span> [, int <span>$offset</span> = 0 ] )
不区分大小写的strpos。实现方式跟下面的类似,主要是使用一份拷贝然后将需要比较的字符串转换成小写字符后进行再进行查找。
stristr
<span>string</span> <span>stristr</span> ( <span>string</span> <span>$haystack</span>, <span>mixed</span> <span>$needle</span> [, bool <span>$before_needle</span> = <span>false</span> ] )
不区分大小写的strstr。
核心源码
<span>//</span><span> 拷贝一份haystack</span> haystack_dup =<span> estrndup(haystack, haystack_len); </span><span>if</span> (Z_TYPE_P(needle) ==<span> IS_STRING) { </span><span>char</span> *<span>orig_needle; </span><span>if</span> (!<span>Z_STRLEN_P(needle)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, </span><span>"</span><span>Empty needle</span><span>"</span><span>); efree(haystack_dup); RETURN_FALSE; } orig_needle </span>=<span> estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle)); </span><span>//</span><span> 调用php_stristr函数找出orig_needle的值。</span> found =<span> php_stristr(haystack_dup, orig_needle, haystack_len, Z_STRLEN_P(needle)); efree(orig_needle); } </span><span>else</span><span> { </span><span>if</span> (php_needle_char(needle, needle_char TSRMLS_CC) !=<span> SUCCESS) { efree(haystack_dup); RETURN_FALSE; } needle_char[</span><span>1</span>] = <span>0</span><span>; found </span>= php_stristr(haystack_dup, needle_char, haystack_len, <span>1</span><span>); } </span><span>if</span><span> (found) { found_offset </span>= found -<span> haystack_dup; </span><span>if</span><span> (part) { RETVAL_STRINGL(haystack, found_offset, </span><span>1</span><span>); } </span><span>else</span><span> { RETVAL_STRINGL(haystack </span>+ found_offset, haystack_len - found_offset, <span>1</span><span>); } } </span><span>else</span><span> { RETVAL_FALSE; } </span><span>//</span><span> 释放变量</span> efree(haystack_dup);
可以知道,found是从php_stristr中得到的,继续查看php_stristr函数:
PHPAPI <span>char</span> *php_stristr(<span>char</span> *s, <span>char</span> *<span>t, size_t s_len, size_t t_len) { php_strtolower(s, s_len); php_strtolower(t, t_len); </span><span>return</span> php_memnstr(s, t, t_len, s +<span> s_len); }</span>
这个函数的功能就是将字符串都转成小写之后调用php_mennstr函数来查找needle在haystack第一次出现的位置。
总结
因为strpos/stripos返回的是位置,位置从0开始计算,所以判断查找失败都用 === FALSE 更适合。
阅读PHP的源码收获挺多,一方面可以知道某个函数的具体实现原理是怎样的,另一方面可以学习到一些编程优化方案。
到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
如果本文对你有帮助,望点下推荐,谢谢^_^

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

PHP中int类型转字符串的方法详解在PHP开发中,经常会遇到将int类型转换为字符串类型的需求。这种转换可以通过多种方式实现,本文将详细介绍几种常用的方法,并附带具体的代码示例来帮助读者更好地理解。一、使用PHP内置函数strval()PHP提供了一个内置函数strval(),可以将不同类型的变量转换为字符串类型。当我们需要将int类型转换为字符串类型时,

标题:Golang中判断字符串是否以指定字符结尾的方法在Go语言中,有时候我们需要判断一个字符串是否以特定的字符结尾,这在处理字符串时十分常见。本文将介绍如何使用Go语言来实现这一功能,同时提供代码示例供大家参考。首先,让我们来看一下Golang中如何判断一个字符串是否以指定字符结尾的方法。Golang中的字符串可以通过索引来获取其中的字符,而字符串的长度可

Golang中如何检查字符串是否以特定字符开头?在使用Golang编程时,经常会遇到需要检查一个字符串是否以特定字符开头的情况。针对这一需求,我们可以使用Golang中的strings包提供的函数来实现。接下来将详细介绍如何使用Golang检查字符串是否以特定字符开头,并附上具体的代码示例。在Golang中,我们可以使用strings包中的HasPrefix

1、首先打开pycharm,进入到pycharm主页。2、然后新建python脚本,右键--点击new--点击pythonfile。3、输入一段字符串,代码:s="-"。4、接着需要把字符串里面的符号重复20次,代码:s1=s*20。5、输入打印输出代码,代码:print(s1)。6、最后运行脚本,在最底部会看到我们的返回值:-就重复了20次。

解决PHP中16进制转字符串出现中文乱码的方法在PHP编程中,有时候我们会遇到需要将16进制表示的字符串转换为正常的中文字符的情况。然而,在进行这个转换的过程中,有时会遇到中文乱码的问题。这篇文章将为您提供解决PHP中16进制转字符串出现中文乱码的方法,并给出具体的代码示例。使用hex2bin()函数进行16进制转换PHP内置的hex2bin()函数可以将1

PHP字符串匹配技巧:避免模糊包含表达式在PHP开发中,字符串匹配是一个常见的任务,通常用于查找特定的文本内容或验证输入的格式。然而,有时候我们需要避免使用模糊的包含表达式来确保匹配的准确性。本文将介绍一些在PHP中进行字符串匹配时避免模糊包含表达式的技巧,并提供具体的代码示例。使用preg_match()函数进行精确匹配在PHP中,可以使用preg_mat

PHP字符串操作:有效去除空格的实用方法在PHP开发中,经常会遇到需要对字符串进行去除空格操作的情况。去除空格可以使得字符串更加整洁,方便后续的数据处理和显示。本文将介绍几种有效的去除空格的实用方法,并附上具体的代码示例。方法一:使用PHP内置函数trim()PHP内置函数trim()可以去除字符串两端的空格(包括空格、制表符、换行符等),非常方便且简单易用

PHP作为一种广泛应用于开发Web应用程序的脚本语言,其字符串处理功能十分强大。在日常开发中,经常会遇到需要删除字符串的操作,特别是删除字符串的最后两个字符。本文将介绍两种PHP实现删除字符串最后两个字符的技巧,并提供具体的代码示例。技巧一:使用substr函数PHP中的substr函数用于返回字符串的一部分。通过指定字符串和起始位置,我们可以轻松地删除字符
