Порівняння рядків із використанням '==' та 'strcmp ()'


334

Здається, що ===оператор PHP чутливий до регістру. То є причина використовувати strcmp()?

Чи безпечно робити щось подібне?

if ($password === $password2) { ... }

10
Що стосується чутливості до регістру strcmp?
kennytm

1
@KennyTM: залежно strcmpвід регістру. У деяких мовах, як-от VB, порівняння рядків може не бути, і, таким чином, повертається інший результат. Однак у PHP це не так.
cHao

13
@jie: Ви можете використовувати ===замість того, ==що '0XAB' == '0xab'це правда.
kennytm

17
використовувати === замість == важливо, оскільки порівняння будь-якого рядка з 0 з == поверне справжнє, що, очевидно, помилково ...
Карл Адлер

4
@Kenny Також '0xAB' == '171'
Сурма

Відповіді:


329

Причина використовувати це тому, що strcmp

повертає <0, якщо str1 менше str2; > 0, якщо str1 більше, ніж str2, і 0, якщо вони рівні.

===тільки повертається trueабо false, це не говорить вам, яка "більша" рядок.


9
icic tho в моєму випадку, мені не потрібно знати, яка струна більша :)
Jiew Meng

154
зЬгстр з відповідними рядками взяв 0.207852 секунд STRCMP з незбіжними рядками взяли 0.215276 секунд === з співпадаючими рядками взяли 0.067122 секунд === з незбіжними рядками взяли 0.057305 секунд snipplr.com/view/758

3
Інше використання strcmp - це сортування. Щоб було більш чітко про сортування. strcmp () повертає <0, якщо string1 сортує перед string2,> 0, якщо string2 сортує перед string1 або 0, якщо вони однакові. Наприклад, $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); повернеться більше нуля, як aaao сортує перед aabo.
HTML Man

20
Чому ця відповідь отримує найбільше відгуків? Я виступаю проти, тому що це питання заслуговує на відповідь, але не "правильна" відповідь. Правильною відповіддю має бути "Використовувати ===", як багато людей вже говорили в інших відповідях.
onur güngör

2
@onur Güngör На насправді, це робить відповідь на питання оп, яка є So is there any reason to use strcmp() ?, в той час як відповідь Postfuturist вона не відображається . О, чорт ... не один відповідь , здавалося , НЕ компілювати одразу використання в strcmp(), в виконанні з ===, і поганий надійності з ==строкових порівнянь ... так що я додав міну до списку.
Бальміпур

222

Ніколи не слід використовувати ==для порівняння рядків. ===гаразд.

$something = 0;
echo ('password123' == $something) ? 'true' : 'false';

Просто запустіть наведений вище код і побачите чому.

$something = 0;
echo ('password123' === $something) ? 'true' : 'false';

Тепер це трохи краще.


19
== не є проблемою лише для різних типів. Іноді це дасть несподівані результати, навіть якщо обидві сторони є рядком. Спробуйте "1e3" == '1000'
Сурма

3
як 0 == 'password123'?
Енді Лобель

24
@AndyLobel PHP примушує "password123" до числа, використовуючи незвичні правила порівняння, оскільки інший операнд - це число, що рядок, як і більшість, примушує до числа 0, і PHP повертає істинне для порівняння.
постфутурист

8
Швидкий var_dump ((int) 'password123'); допомогли мені повністю зрозуміти, чому це сталося ... ** Збентежено ** ... Мені дуже подобається оператор ===
Карлтон

3
це чітко, використовуючи '==', якщо один з двох операндів можна ввести до числа, php переводить обидва операнди на числа, і більше, якщо рядок, що не є числом, передається на число, воно приймає значення нуль, в результаті дорівнює нулю, тож результат порівняння з простим '==' може щось небажане
Лука C.

98

Не використовуйте == в PHP. Це не зробить те, що ви очікуєте. Навіть якщо ви порівнюєте рядки з рядками, PHP неявно відкине їх на плаваючі та зробить числове порівняння, якщо вони здаються числовими.

Наприклад, '1e3' == '1000'повертає true. Ви повинні використовувати ===замість цього.


16
Але можна просто ===.
Роман Ньюаза

11
@ Роман Так, але багато PHP програмістів не знають, що їм це потрібно робити. Звідси попередження.
Сурма

5
@Antimin Так чому б не сказати їм, що вони повинні робити у своїй відповіді?
Тім

43

Ну .. Відповідно до цього звіту про помилки в PHP , ви навіть можете отримати 0wned.

<?php 
    $pass = isset($_GET['pass']) ? $_GET['pass'] : '';
    // Query /?pass[]= will authorize user
    //strcmp and strcasecmp both are prone to this hack
    if ( strcasecmp( $pass, '123456' ) == 0 ){
      echo 'You successfully logged in.';
    }
 ?>

Це дає вам попередження, але все ж обійти порівняння.
Ви повинні робити так, ===як запропонував @postfuturist.


5
Нічого +1. Цитата за посиланням: "Встановлено поведінку для функції, яка отримує неправильний тип аргументів, щоб повернути нуль". Це дивовижно, враховуючи, що посібник просто говорить так: "Повертає <0, якщо str1 менше str2;> 0, якщо str1 більше, ніж str2, і 0, якщо вони рівні". Null не згадується як можливість, але на таких сторінках, як сторінка substr man, він згадується. зітхання
Джеррі

Але чи те ж саме відбувається, коли метод форми розміщується після…?
3лох

@NikhilGeorge Це так, тут йдеться про strcmp. Не має значення, з якими входами порівнювати.
Аджит

Хоча у звіті про помилку сказано, що було непогано повернути нуль, це неправильно. Усі офіційні версії PHP від ​​PHP 4.3 до PHP 7.3 не повертають нуль з цих функцій. Я підозрюю, що це може бути альфа-чи бета-версія, і незалежно від того, що помилка закрита, недійсна, вона була виправлена. Докладні відомості див. У 3v4l.org/Zq8tM , де видно, що це впливає на HHVM 3.11 - 3.19.
Тімо Тіхоф

33

Завжди пам’ятайте, при порівнянні рядків слід використовувати ===оператор (суворе порівняння), а не == оператор (вільне порівняння).


8
Власне, я думаю, що можна сміливо сказати, що вам слід користуватися, ===порівнюючи що- небудь .
rink.attendant.6

22

Підбиття підсумків всіх відповідей:

  • ==є поганою ідеєю для порівняння рядків.
    Це дасть вам "дивовижні" результати у багатьох випадках. Не віриш.

  • === це добре, і дасть вам найкращі показники.

  • strcmp() слід використовувати, якщо вам потрібно визначити, який рядок "більший", як правило, для сортування операцій.


20

Використання ==може бути небезпечним.

Зауважте, що вона може привласнити змінну до іншого типу даних, якщо два будуть різними.

Приклади:

  • echo (1 == '1') ? 'true' : 'false';
  • echo (1 == true) ? 'true' : 'false';

Як бачите, ці двоє є різними типами, але результат - trueце може бути не те, що очікуватиме ваш код.

Використовуючи ===, проте, рекомендуються в якості тесту показує , що це трохи швидше , ніж strcmp()та його регістронезавісімого альтернативи strcasecmp().

Швидке гуглювання кричить це порівняння швидкості: http://snipplr.com/view/758/


1
Іноді це відкидає їх на інший тип, навіть якщо вони вже мають той самий тип.
Сурма

навіть при порівнянні двох рядків, які представляли ціле число, як "012" == "12"php, змінили тип обох рядків на цілий, 12 == 12а потім повернули true.
GoTo


6

strcmp поверне різні значення залежно від середовища, в якому він працює (Linux / Windows)!

Причина в тому, що у ньому є помилка, як йдеться у звіті про помилку https://bugs.php.net/bug.php?id=53999

Будь ласка, поводьтеся обережно !! Дякую


Це завжди буде 0, якщо рядки рівні, хоча. +1 за те, щоб бути уважними щодо турботи про будь-яке інше значення, окрім 0.
Контракт професора Фолкена порушив

4

Ви можете використовувати, strcmp()якщо хочете замовити / порівняти рядки лексикографічно . Якщо ви просто хочете перевірити рівність, то ==це просто добре.


1
Як в усорті . Насправді це в значній мірі зроблено для сортування.
Чарльз

@Charles Спасибі Вікіпедія змусила очі засклитись.
cbednarski

1
Щоб було більш чітко про сортування. strcmp () повертає <0, якщо string1 сортує перед string2,> 0, якщо string2 сортує перед string1 або 0, якщо вони однакові. Наприклад, $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); повернеться більше нуля, як aaao сортує перед aabo.
HTML Man

@postfuturist Я впевнений, що це помилка друку ===.
попіл

4

Також функція може допомогти в сортуванні. Щоб було більш чітко про сортування. strcmp () повертає менше 0, якщо string1 сортує перед string2, більше 0, якщо string2 сортує перед string1 або 0, якщо вони однакові. Наприклад

$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string,$second_string);

Функція повернеться більше нуля, оскільки aaao сортує перед aabo.


0

PHP Замість використання алфавітного сортування використовуйте значення ASCII символу для порівняння. Малі літери мають більше значення ASCII, ніж великі . Краще використовувати оператор ідентичності === для проведення такого роду порівняння. strcmp () - функція для порівняння бінарних безпечних рядків. Він бере два рядки як аргументи і повертає <0, якщо str1 менше str2; > 0, якщо str1 більше, ніж str2, і 0, якщо вони рівні. Існує також нечутлива до регістру версія з назвою strcasecmp (), яка спочатку перетворює рядки в малі регістри, а потім порівнює їх.


0

if ($password === $password2) { ... }це не є безпечною справою, коли порівнювати паролі чи хеші паролів, коли один із входів керується користувачем.
У такому випадку він створює оракул хронометражу, що дозволяє зловмисникові отримувати фактичний хеш пароля з різниць у часі виконання.
Використовуйте if (hash_equals($password, $password2)) { ... }натомість, тому що hash_equals виконує "порівняння між строками атаки тимчасової атаки".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.