深入理解PHP之strpos
概述
在php中经常用 strpos
判断字符串是否在另一个字符串中存在, 本文介绍 strpos
函数及其实现。
strpos应用
<?php
/* strpos示例 */
// test
echo 'match:', strpos('xasfsdfbk', 'xasfsdfbk') !== false ? 'true' : 'false', ';', PHP_EOL;
echo 'match:', strpos('xasfsdfbk', 'fbk') !== false ? 'true' : 'false', ';', PHP_EOL;
echo 'match:', strpos('xasfsdfbk', 'xs') != false ? 'true' : 'false', ';', PHP_EOL;
echo 'match:', strpos('xasfsdfbk', 'sfs') !== false ? 'true' : 'false', ';', PHP_EOL;
// code
strpos('xasfsdfbk', 'sfs');
Warning:
strpos
函数可能返回布尔值FALSE
,但也可能返回等同于FALSE
的非布尔值。请阅读 布尔类型章节以获取更多信息。应使用===
运算符来测试此函数的返回值。
strpos系列函数
函数 | 描述 | 版本 |
---|---|---|
strpos | 查找字符串首次出现的位置 | PHP 4, PHP 5, PHP 7 |
stripos | 查找字符串首次出现的位置(不区分大小写) | PHP 5, PHP 7 |
strrpos | 计算指定字符串在目标字符串中最后一次出现的位置 | PHP 4, PHP 5, PHP 7 |
strripos | 计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写) | PHP 5, PHP 7 |
mb_strpos | 查找字符串在另一个字符串中首次出现的位置 | PHP 4 >= 4.0.6, PHP 5, PHP 7 |
strstr | 查找字符串的首次出现 | PHP 4, PHP 5, PHP 7 |
stristr | strstr() 函数的忽略大小写版本 | PHP 4, PHP 5, PHP 7 |
substr_count | 计算字串出现的次数 | PHP 4, PHP 5, PHP 7 |
mb* 相关的函数也可, 比如说mb_strpos是基于字符数执行一个多字节安全的 strpos() 操作。
PHP(strpos)源码
strpos(ext/standard/string.c)
```
PHP_FUNCTION(strpos)
{
zval *needle;
zend_string *haystack;
char *found = NULL;
char needle_char[2];
zend_long offset = 0;
ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &needle, &offset) == FAILURE) {
return;
}
else
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STR(haystack)
Z_PARAM_ZVAL(needle)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(offset)
ZEND_PARSE_PARAMETERS_END();
endif
if (offset < 0) {
offset += (zend_long)ZSTR_LEN(haystack);
}
if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
RETURN_FALSE;
}
if (Z_TYPE_P(needle) == IS_STRING) {
if (!Z_STRLEN_P(needle)) {
php_error_docref(NULL, E_WARNING, "Empty needle");
RETURN_FALSE;
}
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
Z_STRVAL_P(needle),
Z_STRLEN_P(needle),
ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
} else {
if (php_needle_char(needle, needle_char) != SUCCESS) {
RETURN_FALSE;
}
needle_char[1] = 0;
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
needle_char,
1,
ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
}
if (found) {
RETURN_LONG(found - ZSTR_VAL(haystack));
} else {
RETURN_FALSE;
}
}
<h3>php_memnstr(main/php.h)</h3>
<ul><li><a href="https://github.com/php/php-src/blob/master/main/php.h" rel="nofollow noreferrer">PHP源码地址</a></li></ul>
define php_memnstr zend_memnstr /* 338 line*/
<h3>zend_memnstr(Zend/zend_operators.h)</h3>
<ul><li><a href="https://github.com/php/php-src/blob/master/Zend/zend_operators.h" rel="nofollow noreferrer">PHP源码地址</a></li></ul>
/*
此函数的作用是在haystack中查找needle,如果不存在返回null,如果存在,返回指向haystack中needle头字符的指针
*/
zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const char *end)
{
const char *p = haystack;
const char ne = needle[needle_len-1];
ptrdiff_t off_p;
size_t off_s;if (needle_len == 1) {
return (const char *)memchr(p, *needle, (end-p));
}off_p = end - haystack;
off_s = (off_p > 0) ? (size_t)off_p : 0;if (needle_len > off_s) {
return NULL;
}if (EXPECTED(off_s < 1024 || needle_len < 3)) {
// 第一个优化,只查找end - needle_len次
end -= needle_len;while (p <= end) {
// 第二个优化,先判断字符串的开头和结尾是否一样再判断整个字符串
if ((p = (const char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
if (!memcmp(needle, p, needle_len-1)) {
return p;
}
} if (p == NULL) {
return NULL;
} p++;
} return NULL;
} else {
return zend_memnstr_ex(haystack, needle, needle_len, end);
}
}
<h3>memchr(string.h)</h3>
<ul><li><a href="https://github.com/torvalds/linux/blob/master/lib/string.c" rel="nofollow noreferrer">Linux内核版-源码地址</a></li></ul>
/*
头文件:#include <string.h>
定义函数:void * memchr(const void *s, char c, size_t n);
函数说明:memchr()从头开始搜寻s 所指的内存内容前n 个字节,直到发现第一个值为c 的字节,则返回指向该字节的指针。
返回值:如果找到指定的字节则返回该字节的指针,否则返回0。
*/
ifndef __HAVE_ARCH_MEMCHR
void *memchr(const void *s, int c, size_t n)
{
const unsigned char *p = s;
while (n-- != 0) {
if ((unsigned char)c == *p++) {
return (void *)(p - 1);
}
}
return NULL;
}
EXPORT_SYMBOL(memchr);
endif
<h3>memcmp(string.h)</h3>
<ul><li><a href="https://github.com/torvalds/linux/blob/master/lib/string.c" rel="nofollow noreferrer">Linux内核版-源码地址</a></li></ul>
/* 字符串函数memcmp
原型:extern int memcmp(void *buf1, void *buf2, unsigned int count);
功能:比较内存区域buf1和buf2的前count个字节
说明:当buf1<buf2时,返回值<0
当buf1=buf2时,返回值=0
当buf1>buf2时,返回值>0
*/
ifndef __HAVE_ARCH_MEMCMP
undef memcmp
__visible int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
return res;
}
EXPORT_SYMBOL(memcmp);
endif
<h2>提示</h2>
<p>strpos函数对大小写敏感。</p>
<h2>参考</h2>
<ul>
<li><a href="http://php.net/manual/zh/function.strpos.php" rel="nofollow noreferrer">php strpos官方文档</a></li>
<li><a href="https://segmentfault.com/a/1190000015776297">字符串查找算法</a></li>
</ul>
原文地址:https://segmentfault.com/a/1190000015786500
深入理解PHP之strpos的更多相关文章
- [译] 理解PHP内部函数的定义(给PHP开发者的PHP源码-第二部分)
文章来自:http://www.hoohack.me/2016/02/10/understanding-phps-internal-function-definitions-ch 原文:https:/ ...
- PHP代码审计04之strpos函数使用不当
前言 根据红日安全写的文章,学习PHP代码审计的第四节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一个实例来加深巩固,这是之前写的,有兴趣可以去看看: PHP代码 ...
- 理解CSS视觉格式化
前面的话 CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...
- 彻底理解AC多模式匹配算法
(本文尤其适合遍览网上的讲解而仍百思不得姐的同学) 一.原理 AC自动机首先将模式组记录为Trie字典树的形式,以节点表示不同状态,边上标以字母表中的字符,表示状态的转移.根节点状态记为0状态,表示起 ...
- 理解加密算法(三)——创建CA机构,签发证书并开始TLS通信
接理解加密算法(一)--加密算法分类.理解加密算法(二)--TLS/SSL 1 不安全的TCP通信 普通的TCP通信数据是明文传输的,所以存在数据泄露和被篡改的风险,我们可以写一段测试代码试验一下. ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念
一.前言 DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...
- 学习AOP之透过Spring的Ioc理解Advisor
花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...
- ThreadLocal简单理解
在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...
随机推荐
- Bing必应地图中国API-显示兴趣点 (转)
Bing必应地图中国API-显示兴趣点 2011-05-24 14:29:55| 分类: Bing&Google|字号 订阅 在地图上显示一个兴趣点,这个应用可以说是最简单但是最广泛 ...
- tflearn 保存模型重新训练
from:https://stackoverflow.com/questions/41616292/how-to-load-and-retrain-tflean-model This is to cr ...
- 远程报错:这可能是由于credssp加密oracle修正
- POJ1279 Art Gallery 多边形的核
POJ1279 给一个多边形 求它的核的面积 所谓多边形的核 是多边形中的一个点集 满足其中的点与多边形边上的点的连线全部在多边形中 用多边形的每一条边所在的直线去切整个坐标平面 得到的一个凸包就是核 ...
- 杂项:game_navigation
ylbtech-杂项:game_navigation 1.返回顶部 1. 2. 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 作者:ylbtech出处: ...
- openstack dnsmasq彭祖
Openstack dnsmasq配置域名解析,openstackdnsmasq vi /etc/nova/nova.conf 在[DEFAULT]添加 dnsmasq_config_file=/et ...
- ECS服务器配置密钥登录及常用日志
一.介绍 1.SSH(22端口)是Secure Shell Protocol的简写,由IETF网络工作小组(Network Working Group)制定:在进行数据传输之前,SSH先对联机数据包通 ...
- SpringBoot中使用spring-data-jpa 数据库操作(下)
- Java 链式写法
Java链式写法,子类继承父类的属性,也可以返回子类的对象,只是需要重写基类的Set方法 public class MyLS { public static void main(String[] ar ...
- bzoj 1626: [Usaco2007 Dec]Building Roads 修建道路【最小生成树】
先把已有的边并查集了,然后MST即可 记得开double #include<iostream> #include<cstdio> #include<algorithm&g ...