strstr 또는 strpos가 선호되는 방법은 무엇입니까?


84

많은 개발자가 strstr과 strpos를 모두 사용하여 하위 문자열의 존재를 확인하고 있음을 알았습니다. 그들 중 하나가 선호되며 그 이유는 무엇입니까?


2
당신이 언급 한 벤치 마크는 strstr이 아닌 substr에 대한 것입니다
Flask

답변:


125

PHP 온라인 매뉴얼에서 :

특정 바늘이 건초 더미 내에서 발생하는지 확인하려면 strpos() 대신 더 빠르고 메모리 집약적 인 함수를 사용하십시오.


13
+1, strpos 또는 stripos를 사용할 수 있습니다. 그리고 === FALSE 사용에 대한 PHP 문서의 경고를 확인하는 것을 잊지 마십시오;
fedmich

7
fedmich의 의견에 대해 자세히 설명하기 위해 : 저는 항상 if(strpos($haystack,$needle) !== false) { // do something }, 절대로 사용 하지 않습니다 if(strpos($haystack,$needle)) { // do bad things }. 이가의 맨 처음에 strpos있으면 0을 반환 하고 0은 거짓으로 간주됩니다. 참으로 평가됩니다. 거짓으로 평가됩니다. $needle$haystack(0 == false)(0 === false)
Butkus

1
C에서 온 사람들은 strchr 함수 사용에 대해 생각할 수 있지만 PHP에서는 실제로 strstr 의 별칭 이므로 strpos 가 더 나은 선택입니다.
e2-e4

38

여기 에 몇 가지 다른 답변 (+ 벤치 마크)이 있습니다. 제 질문에 대해 거의 똑같습니다 (질문 할 때 귀하의 답변을 몰랐습니다).


그 동안 나는 또한 내가 각 관련 기능에 1000000 번 실행 내 자신의 벤치 마크 테스트를했다 ( strstr(), strpos(), stristr()stripos()).
코드는 다음과 같습니다.

<?php

function getmicrotime() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float) $usec + (float) $sec);
}

$mystring = 'blahblahblah';  
$findme = 'bla';  

echo 'strstr & strpos TEST:<pre>';
$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) strstr($mystring, $findme);
$time_needed_strstr = getmicrotime() - $time_start;
echo 'strstr():            ',
    round( $time_needed_strstr , 8 ). PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) stristr($mystring, $findme);
$time_needed_stristr = getmicrotime() - $time_start;
echo 'stristr():           ',
    round( $time_needed_stristr , 8 ) . PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) strpos($mystring, $findme) !== false;
$time_needed_strpos = getmicrotime() - $time_start;
echo 'strpos() !== false:  ',
    round( $time_needed_strpos , 8 ) . PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) stripos($mystring, $findme) !== false;
$time_needed_stripos = getmicrotime() - $time_start;
echo 'stripos() !== false: ',
    round( $time_needed_stripos , 8 ) . PHP_EOL;

echo PHP_EOL;

echo 'time_needed_stristr - time_needed_strstr: ',
     round( $time_needed_stristr - $time_needed_strstr , 8) . PHP_EOL;
echo 'time_needed_stripos - time_needed_strpos: ',
     round( $time_needed_stripos - $time_needed_strpos , 8) . PHP_EOL;

echo PHP_EOL;

echo 'time_needed_strstr  - time_needed_strpos:  ',
     round( $time_needed_strstr - $time_needed_strpos , 8) . PHP_EOL;
echo 'time_needed_stristr - time_needed_stripos: ',
     round( $time_needed_stristr - $time_needed_stripos , 8) . PHP_EOL;

echo '</pre>';

?>

그리고 strpos()이것이 승자 임을 보여주는 첫 번째 출력입니다 .

strstr & strpos TEST:
strstr():            2.39144707
stristr():           3.65685797
strpos() !== false:  2.39055395
stripos() !== false: 3.54681897

time_needed_stristr - time_needed_strstr: 1.2654109
time_needed_stripos - time_needed_strpos: 1.15626502

time_needed_strstr  - time_needed_strpos:  0.00089312
time_needed_stristr - time_needed_stripos: 0.110039 

다음 출력은 첫 번째 출력과 유사합니다 ( strpos()다시 승자가됩니다).

strstr & strpos TEST:
strstr():            2.39969015
stristr():           3.60772395
strpos() !== false:  2.38610101
stripos() !== false: 3.34951186

time_needed_stristr - time_needed_strstr: 1.2080338
time_needed_stripos - time_needed_strpos: 0.96341085

time_needed_strstr  - time_needed_strpos:  0.01358914
time_needed_stristr - time_needed_stripos: 0.25821209

다음은이 경우 strstr()승자가 되기 때문에 더 흥미로운 또 다른 것입니다 .

strstr & strpos TEST:
strstr():            2.35499191
stristr():           3.60589004
strpos() !== false:  2.37646604
stripos() !== false: 3.51773095

time_needed_stristr - time_needed_strstr: 1.25089812
time_needed_stripos - time_needed_strpos: 1.14126492

time_needed_strstr  - time_needed_strpos:  -0.02147412
time_needed_stristr - time_needed_stripos: 0.08815908

이것은 실제로 영향을 미치기 어려운 "환경 적 상황"에 의존 할 수 있으며 문자열이 다른 문자열에 존재하는지 여부를 확인하는 경우 이와 같이 "마이크로 최적화 작업"의 결과를 변경할 수 있음을 의미합니다.

그러나 나는 대부분의 경우strpos() 에 비해 승자 라고 생각 합니다 strstr().

이 테스트가 누군가에게 도움이 되었기를 바랍니다.


3
이 벤치 마크는 유용하지만 메모리 소비를 측정하지 않으며 kbyte 또는 mbyte와 같은 긴 문자열도 고려하지 않습니다.

어? @ user133408 긴 문자열과 큰 바이트 문자열은 더 오래 걸립니다.
NiCk Newman

7

많은 개발자 strpos마이크로 최적화 목적으로 사용 합니다.

사용 strstr은 결과 문자열이 부울 컨텍스트에서 false로 해석 될 수없는 경우에만 작동합니다.


11
마이크로 최적화가 아니라 작업에 적합한 기능을 사용하여 호출 됩니다 . 문자열의 위치를 ​​원하면 strpos(). 해당 위치 뒤에 하위 문자열을 원하면 strstr().
Alnitak 2011

1
@Alnitak : 내가 말한 것. 문자열의 존재 여부를 확인하려면 해당 기능이 있습니다. 실제로 위치가 필요하다면 다른 위치가 있습니다. -실제로 직위가 필요하지 않고 직위를 조사 할 때 "직무에 적합한 기능을 사용"하는 것은 거의 없습니다. 의도는 분명히 마이크로 초 거리를 최적화하는 것입니다. (당신이 인용 무엇을하는 것이 아닌가?)
마리오

1
@mario 그러나 부분 문자열이 존재하는지 확인 하는 유일한 목적을 가진 함수는 없습니다 . 하위 문자열 (발견 된 경우) 의 위치 는 실제로 찾은 경우 무료 정보입니다. OTOH 는 필요한 것 이상을 strstr수행 하기 때문에 속도가 느립니다.
Alnitak 2011

@Alnitak : 뉴스가 아니라 당신을 염두에 두십시오. 성능 차이를 지적하는 것에 대해 매우 단호한 것 같습니다. 이는 마이크로 최적화의 확실한 신호입니다. 프로파일 러에서 깜빡 거리지 않습니다 . 차이를 만드는 부분은 코드 가독성입니다.
mario

@mario 실제로 나는 성능에 대해 아주 약간만 신경을 쓸 것입니다. 나는 작업에 적합한 기능을 사용하는 데 매우 신경을
씁니다

0

strpos ()는 건초 더미에서 특정 바늘이있는 위치를 감지합니다. stristr ()은 바늘이 건초 더미의 어디에 있는지 테스트합니다.

따라서 strpos ()는 더 빠르고 메모리 소모가 적습니다.

strstr ()의 이유 : 바늘이 문자열의 시작 부분에 있으면 strpos는 0을 반환합니다 (따라서 === false로 확인해야합니다).


6
그것은 완전히 가짜 설명입니다- strstr()바늘 앞뒤의 모든 것을 반환하므로 먼저 strpos() 해당 부분 문자열을 생성해야 합니다. 그것이 성능 저하가있는 곳입니다.
Alnitak 2011

-2

나는 strstr()가독성과 쉬운 코딩을 선호한다 .. strpos() !==false 약간 혼란스러워 ..


1
strstr너무 비슷한입니다strtr
마틴 Briedis

strstr엄격한 비교가 필요합니다. 예 :('123450', '0')
Elvis Ciotti
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.