PHP strpos,strstr,strpbrk这几个函数有什么区别

22 Feb 2019 Category: php

确定一个字符串是否在另一个字符串中,在PHP中有很多方法实现。strpos,strstr,strpbrk这几个函数都可以实现。那么这几个函数有什么不同呢?

strstr

strstr — 查找字符串的首次出现,别名strchar

strstr ( string $haystack , mixed $needle [, bool $before_needle = FALSE ] ) : string

返回 haystack 字符串从 needle 第一次出现的位置开始到 haystack 结尾的字符串。

如果$before_needle=true则返回第一次出现的位置前面的字符。如果字符不存在,则返回false。

如果needle不是一个字符串,那么它将被转化为整型并且作为字符的序号来使用。


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), 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), needle_char, 1, ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
}

if (found) {
	found_offset = found - ZSTR_VAL(haystack);
	if (part) {
		RETURN_STRINGL(ZSTR_VAL(haystack), found_offset);
	} else {
		RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
	}
}

strpos

查找字符串首次出现的位置。


strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int

返回 needle 在 haystack 中首次出现的数字位置。查询从offset开始。offset不影响输出的数值。只用于跳过不查询的字符串。

官方文档的Note中:

如果你仅仅想确定 needle 是否存在于 haystack 中,请使用速度更快、耗费内存更少的 strpos() 函数。

以下是strpos 的源码


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;
}

对比两个函数的内部实现,除了offset之外,其实际差别在于strstr最后返回了字符串,strpos返回的是一个数。由于字符串返回的时候涉及到字符串复制的过程,因此会有速度和内存上的损耗。在性能上,strpos 会比strstr好一点点。

可以看一下网上的测试效果,测试效果地址

strpbrk

strpbrk — 在字符串中查找一组字符的任何一个字符。返回一个以找到的字符开始的子字符串。如果没有找到,则返回 FALSE。


strpbrk ( string $haystack , string $char_list ) : string

strpbrk() 函数在 haystack 字符串中查找 char_list 中的字符。


for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
	for (cl_ptr = ZSTR_VAL(char_list); cl_ptr < (ZSTR_VAL(char_list) + ZSTR_LEN(char_list)); ++cl_ptr) {
		if (*cl_ptr == *haystack_ptr) {
			RETURN_STRINGL(haystack_ptr, (ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - haystack_ptr));
		}
	}
}

相对于上面两个函数,strpbrk相对粗暴些,直接两个循环,实现字符的查找。在性能上,应该是这三个函数垫底的了。

总结

以字符串ABCGCAC为例。

strpos 返回的是完整匹配查询字符串的第一次出现位置。strpos(‘ABCGCAC’,’CA’)返回结果是4。

strpbrk 返回的是字符列表中匹配的任意一个字符第一次出现之后的字符串。 strpbrk(‘ABCGCAC’,’CA’) 返回的内容是ABCGCAC,如果传入整数,会转成字符类型strpbrk(‘ABC13G2CAC’,’123’) 返回13G2CAC

strstr 返回的是完整匹配查询字符串第一次后出现后的字符串,strstr(‘ABCGCAC’,’CA’) 返回结果CAC

道路千万条,性能优化第一条,一点点的提升也是提升,只需要选择函数的时候合理选择。

字符串处理函数中,以下函数传入整数是当做ascii值去查找

1、strpos,stripos,strrpos,strripos 2、strstr,stristr,strrstr,strchar,strrchar

评论