strcmp ()
strcmp 함수
strcmp($string1, $string2);
- 첫번째 인자 자료형($string1): 문자열
- 두번째 인자 자료형($string2): 문자열
- 반환 자료형: int
0을 반환
- 인자로 전달된 두 문자열이 정확히 같다면 0을 반환한다.
- 대소문자를 구별한다. 같은 글자라도 대소문자가 다르면 0을 반환하지 않는다.
1 2 3 4 5 6 7 | <?php echo ‘$str1=”Hello”, $str2=”Hello”<br>’; echo ‘strcmp($str1, $str2)의 출력값:<br>’; $str1 = “Hello”; $str2 = “Hello”; var_dump(strcmp($str1, $str2)); ?> | cs |
$str1=”Hello”, $str2=”Hello”
strcmp($str1, $str2)의 출력값:
int(0)
strcmp($str1, $str2)의 출력값:
int(0)
음수 반환
- 첫 문자열이 두 번째 문자열보다 사전 순서가 앞에 있다면 음수를 반환한다.
- 사전 순서는 아스키 숫자에 의해 결정된다. 예를 들어 a는 97이고, c는 99이다. 따라서 아래 코드의 결과는 음수를 반환한다. (참고로 echo ord(“a”); 를 하면 아스키 숫자를 볼 수 있다.)
- 여기서 주의할 점은 운영체제 별로 반환하는 음수 숫자가 다르다는 점이다. Windows, Linux에서는 -1이 나오고, Mac OS X에서는 경우에는 아스키 값의 차이 값 -2 (=97-99)가 출력된다.[참고3]
1 2 3 4 5 6 7 | <?php echo ‘$str1=”a”, $str2=”c”<br>’; echo ‘strcmp($str1, $str2)의 출력값:<br’; $str1 = “a”; $str2 = “c”; var_dump(strcmp($str1, $str2)); ?> | cs |
$str1=”a”, $str2=”c”
strcmp($str1, $str2)의 출력값:
int(-1)
strcmp($str1, $str2)의 출력값:
int(-1)
- 두 문자열의 시작 문자가 똑같다면, 그 다음 다른 문자가 나올 때까지 비교한다.
- 아래 코드를 보면, 첫 문자열과 두 번째 문자열이 달라지는 부분은 Hello이후의 ‘a’와 ‘c’이다. 첫 문자열의 a의 아스키 코드가 더 작으므로 -1를 반환한다. (앞서 설명한 것처럼 Mac OS X에서는 아스키 값의 차이인 -2 (=97-99)를 반환한다.)
1 2 3 4 5 6 7 | <?php echo ‘$str1=”Helloa”, $str2=”Helloc”<br>’; echo ‘strcmp($str1, $str2)의 출력값:<br>’; $str1 = “Helloa”; $str2 = “Helloc”; var_dump(strcmp($str1, $str2)); ?> | cs |
$str1=”Helloa”, $str2=”Helloc”
strcmp($str1, $str2)의 출력값:
int(-1)
strcmp($str1, $str2)의 출력값:
int(-1)
양수 반환
- 첫 문자열이 두 번째 문자열보다 사전 순서가 뒤에 있다면 양수를 반환한다.
- 아래 코드에서 첫 문자열의 c는 두 번째 문자열의 a보다 사전 순서가 뒤에 있기 때문에, 양수 1를 반환한다.
- 위에서 설명한 것 처럼, Mac OS X에서는 아스키 숫자의 차이(2)를 반환한다.
1 2 3 4 5 6 7 | <?php echo ‘$str1=”c”, $str2=”a”<br>’; echo ‘strcmp($str1, $str2)의 출력값:<br>’; $str1 = “c”; $str2 = “a”; var_dump(strcmp($str1, $str2)); ?> | cs |
$str1=”c”, $str2=”a”
strcmp($str1, $str2)의 출력값:
int(1)
strcmp($str1, $str2)의 출력값:
int(1)
strcmp vs. == vs. === 비교
문자열을 같은 값을 가지는지 비교하기 위해서 strcmp함수 또는 동등 연산자 (==), 일치 연산자 (===)을 사용할 수 있다. 이 3가지 중에서 문자열 비교를 할 때 무엇을 사용하면 좋을까?
결론부터 말하자면, 문자열을 비교할 땐 무조건 일치 연산자(===)을 사용해야 한다. strcmp를 사용할 수도 있지만, 성능면에서 일치 연산자(===)가 훨씬 우수하다. 절대로 동등 연산자(==)를 문자열 비교에 사용하면 안된다. 왜냐하면 동등 연산자는 “자료형 자동변환”에 의해 의도치 않은 결과가 나올 수도 있기 때문이다.
동등연산자(==)를 문자열 비교에 사용하면 안되는 이유
- 동등 연산자(==)는 자료형을 자동으로 바꾸기 때문에, 우리가 생각하기에 같지 않은 값들도 같다고 처리되는 경우가 있다.
- 예를 들어, 아래 코드는 로그인을 위해서 입력 받은 값 $input과 데이터 베이스에 저장된 암호 $password를 비교하여 로그인 처리한다. 입력한 값 $input = “14e4″이고, 저장된 암호 $password=”140000″라고 할 때, 이 둘은 서로 다른 문자열인데 반해, 숫자로는 같은 값을 나타낸다. 14e4는 과학적 표기법(scientific notation)으로 140000와 같은 숫자이기 때문이다. 만약 단순히 이 두 변수를 동등 연산자(==)로 비교하게 된다면, 의도치 않게 false가 아닌 true 값을 반환하게 되고 로그인에 성공하게 된다.
1 2 3 4 5 6 7 8 9 | <?php echo ‘입력받은 값 $input=”14e4″, 저장된 암호 $password=”140000″<br>’; echo ‘if ($password == $input)<br>’; $input = “14e4”; $password = “140000”; if ($password == $input) echo “- true: 로그인 되었습니다.”; else echo “- false: 비밀번호가 다릅니다.”; ?> | cs |
입력받은 값 $input=”14e4″, 저장된 암호 $password=”140000″
if ($password == $input)
– true: 로그인 되었습니다.
if ($password == $input)
– true: 로그인 되었습니다.
- 따라서 문자열의 정확한 비교를 하기 위해서는 strcmp함수 또는 일치 연산자(===)을 사용해야 한다. 하지만 성능면에서 일치 연산자가 우수하므로, 단순 비교를 위해서는 일치 연산자를 사용하고, 두 문자열의 크기(사전적 순서)를 비교할 때는 strcmp 함수를 사용한다.
1 2 3 4 5 6 7 8 9 | <?php echo ‘입력받은 값 $input=”14e4″, 저장된 암호 $password=”140000″<br>’; echo ‘if ($password === $input)<br>’; $input = “14e4”; $password = “140000”; if ($password === $input) echo “- true: 로그인 되었습니다.”; else echo “- false: 비밀번호가 다릅니다.”; ?> | cs |
입력받은 값 $input=”14e4″, 저장된 암호 $password=”140000″
if ($password === $input)
– false: 비밀번호가 다릅니다.
if ($password === $input)
– false: 비밀번호가 다릅니다.
- 일치 연산자(===) 말고 strcmp 함수를 문자열 비교에 사용하는 경우도 있다.
- 일치 연산자는 boolean으로 반환하는 반면, strcmp는 int를 반환하기 때문에 usort, array_intersect 등의 함수에 바로 사용될 수 있다.
- 아래의 코드는 다중 배열의 값들을 사전 순서로 배열하는 예제이다. usort()는 사용자 정의 함수에 따라 배열을 정렬하는 함수이고, 여기서 사용자 정의 함수는 0 또는 양수/음수를 반환해야 한다. 이런 경우 strcmp 함수를 응용할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php function cmp($a, $b) { return strcmp($a[“fruit”], $b[“fruit”]); } $fruits[0][“fruit”] = “lemons”; $fruits[1][“fruit”] = “apples”; $fruits[2][“fruit”] = “grapes”; usort($fruits, “cmp”); print_r($fruits); ?> | cs |
Array
(
[0] => Array
(
[fruit] => apples
)
[1] => Array
(
[fruit] => grapes
)
[2] => Array
(
[fruit] => lemons
)
)
주의할 점: PHP 5.3과 그 이후 몇몇 버젼
- PHP 5.3 (그 이후 몇몇 버젼)에서 strcmp의 인자로 배열을 넣게 되면, NULL 반환한다. 따라서 사용하는 서버의 PHP 버젼이 이에 해당하면 아래와 같은 코드를 조심해야 한다.
- NULL 반환의 문제가 되는 상황을 생각해보면, 아래와 같은 코드로 로그인 인증을 했을 때 심각한 문제가 발생할 수 있다. 입력받은 값 $input이 배열로 들어오게 된다면, 저장된 암호 $password와 상관없이 strcmp($input, $password)는 NULL을 반환하게 된다. NULL == 0 은 true를 반환하게 되고, 로그인이 되어 버린다. 비번이 틀렸는데도 말이다.
- 최신 버젼의 PHP에서는 strcmp 인자의 자료형으로 배열이 못 들어오게 막아 놨기 때문에 이러한 함정이 빠지지 않지만, 항상 일치 연산자(===)의 사용에 익숙해져 있는 것이 좋다.
1 2 3 4 5 6 7 8 9 | <?php echo “strcmp(배열, 문자열): <br>”; $input = array(“any value”); // 실제로는 $input=$_POST[“input”] 식으로 값을 받을 수 있다. $password = “saved password”; if (strcmp($input, $password) == 0) echo “- true: 로그인 되었습니다.”; else echo “- false: 암호가 틀렸습니다.”; ?> | cs |
strcmp(배열, 문자열):
– true: 로그인 되었습니다.
– true: 로그인 되었습니다.
Form Input에 배열(array)를 넣는 방법
- 그럼, 어떻게 입력값에 배열로 넣을 수 있을까?
- GET 방식으로 데이터를 받는다고 할 때, 주소창에 https://주소/?input[]=a 을 하게 되면 $input = array(“a”)와 같이 배열값이 입력된다.
- 아래 예제처럼 코드를 작성하고, 주소창에 http://localhost/파일이름.php/?input[]=a 라고 입력해 보자. 그러면 $input의 자료형이 배열임을 확인할 수 있다.
1 2 3 4 | <?php $input = $_GET[‘input’]; var_dump($input); ?> | cs |
array(1) {
[0]=>
string(1) “a”
}
- POST 방식으로 데이터를 받는다고 할 때도, curl이라는 프로그램을 이용하면 배열값을 입력할 수 있다.
- curl -d input[]=a http://주소/파일.php 이라고 입력하면, $input의 자료형은 배열이된다.
- 또는 아래와 같이 input 태그의 name 속성을 name=”input[]” 으로 바꿔줌으로써 배열값을 입력할 수도 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!DOCTYPE html> <html lang=“en” dir=“ltr”> <head> <meta charset=“utf-8”> <title></title> </head> <body> <form action=“<?php echo $_SERVER[‘PHP_SELF’]?>” method=“post”> 암호: <input type=“text” name=“input[]” value=“”> <input type=“submit”> </form> <?php if ($_SERVER[‘REQUEST_METHOD’] === “POST”) { $input = $_POST[‘input’]; var_dump($input); } ?> </body> </html> | cs |
array(1) {
[0]=>
string(0) “”
}




