Zeichenfolgenvergleich mit '==' vs. 'strcmp ()'

334

Es scheint, dass der ===Betreiber von PHP zwischen Groß- und Kleinschreibung unterscheidet. Gibt es also einen Grund zu verwenden strcmp()?

Ist es sicher, so etwas wie das Folgende zu tun?

if ($password === $password2) { ... }
Jiew Meng
quelle
10
Was hat Groß- und Kleinschreibung zu tun strcmp?
Kennytm
1
@KennyTM: unterscheidet zwischen strcmpGroß- und Kleinschreibung. In einigen Sprachen wie VB ist ein Zeichenfolgenvergleich möglicherweise nicht möglich und würde daher ein anderes Ergebnis liefern. Dies ist jedoch in PHP nicht der Fall.
CHao
13
@jie: Vielleicht möchten Sie ===anstelle von ==weil verwenden, '0XAB' == '0xab'ist wahr.
Kennytm
17
=== anstelle von == zu verwenden ist wichtig, da der Vergleich eines Strings mit == mit == true zurückgibt, was offensichtlich falsch ist ...
Karl Adler
4
@Kenny Also '0xAB' == '171'
Antimon

Antworten:

329

Der Grund, es zu benutzen, ist weil strcmp

gibt <0 zurück, wenn str1 kleiner als str2 ist; > 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind.

===Gibt nur zurück trueoder falsesagt Ihnen nicht, welche Zeichenfolge "größer" ist.

täuschen
quelle
9
In meinem aktuellen Fall muss ich nicht wissen, welche Zeichenfolge größer ist :)
Jiew Meng
154
strcmp mit übereinstimmenden Zeichenfolgen dauerte 0,207852 Sekunden strcmp mit nicht übereinstimmenden Zeichenfolgen dauerte 0,215276 Sekunden === mit übereinstimmenden Zeichenfolgen dauerte 0,067122 Sekunden === mit nicht übereinstimmenden Zeichenfolgen dauerte 0,057305 Sekunden snipplr.com/view/758
3
Die andere Verwendung für strcmp zeigt die Sortierung. Um das Sortieren klarer zu machen. strcmp () gibt <0 zurück, wenn string1 vor string2 sortiert,> 0, wenn string2 vor string1 sortiert, oder 0, wenn sie identisch sind. Zum Beispiel $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); wird größer als Null zurückgeben, da aaao vor aabo sortiert.
HTML Man
20
Warum erhält diese Antwort die meisten positiven Stimmen? Ich stimme ab, denn obwohl es die Antwort ist, die diese Frage verdient, aber nicht die 'richtige' Antwort. Die richtige Antwort sollte "Use ===" sein, wie viele Leute bereits in anderen Antworten gesagt haben.
Onur Güngör
2
@onur güngör Eigentlich ist dies tut beantwortet die Frage , op, das ist So is there any reason to use strcmp() ?, während Postfuturist Antwort nicht. Oh, Hölle ... niemand Antwort schien auf einmal die kompilieren Verwendung von strcmp()der, Leistung von ===und der schlechten Zuverlässigkeit der ==für String - Vergleiche ... so dass ich meine zu der Liste hinzugefügt.
Balmipour
222

Sie sollten niemals ==für den Zeichenfolgenvergleich verwenden. ===ist in Ordnung.

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

Führen Sie einfach den obigen Code aus und Sie werden sehen warum.

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

Das ist ein bisschen besser.

Postfuturist
quelle
19
== ist nicht nur ein Problem für verschiedene Typen. Es gibt manchmal unerwartete Ergebnisse, selbst wenn beide Seiten eine Zeichenfolge sind. Versuchen Sie '1e3' == '1000'
Antimon
3
Wie funktioniert 0 == 'password123'?
Andy Lobel
24
@AndyLobel PHP erzwingt 'password123' unter Verwendung seiner ungeraden losen Vergleichsregeln zu einer Zahl, da der andere Operand eine Zahl ist. Diese Zeichenfolge erzwingt wie die meisten die Zahl 0, und PHP gibt für den Vergleich true zurück.
Postfuturist
8
Ein kurzer var_dump ((int) 'password123'); hat mir geholfen zu verstehen, warum dies passiert ist ... ** verlegen ** ... Ich mag den Operator ===
Carlton
3
Dies liegt daran, dass '==' verwendet wird, wenn einer der beiden Operanden in Zahl umgewandelt werden kann, PHP beide Operanden in Zahlen umwandelt und mehr, wenn eine Zeichenfolge ohne Zahl in Zahl umgewandelt wird, der Wert Null annimmt, was gleich Null ist. Das Ergebnis des Vergleichs mit einfachem '==' kann also etwas Unerwünschtes sein
Luca C.
98

Nicht ==in PHP verwenden. Es wird nicht das tun, was Sie erwarten. Selbst wenn Sie Zeichenfolgen mit Zeichenfolgen vergleichen, wandelt PHP diese implizit in Gleitkommazahlen um und führt einen numerischen Vergleich durch, wenn sie numerisch erscheinen.

Zum Beispiel '1e3' == '1000'gibt true zurück. Sie sollten ===stattdessen verwenden.

Antimon
quelle
16
Aber du kannst einfach ===.
Roman Newaza
11
@ Roman ja, aber viele PHP-Programmierer wissen nicht, dass sie das tun müssen. Daher die Warnung.
Antimon
5
@Antimony Warum sagst du ihnen nicht, was sie in deiner Antwort tun sollen ?
Tim
43

Nun ... laut diesem PHP-Fehlerbericht können Sie sogar 0wned bekommen.

<?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.';
    }
 ?>

Es gibt Ihnen eine Warnung, umgeht aber trotzdem den Vergleich.
Sie sollten das tun, ===was @postfuturist vorgeschlagen hat.

Ajith
quelle
5
Wow +1. Zitat aus dem Link: "Es ist ein etabliertes Verhalten für Funktionen, die den falschen Argumenttyp (die falschen Argumente) erhalten, um null zurückzugeben." Das ist erstaunlich, wenn man bedenkt, dass das Handbuch nur Folgendes sagt: "Gibt <0 zurück, wenn str1 kleiner als str2 ist;> 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind". Null wird nicht als Möglichkeit erwähnt, wird jedoch auf Seiten wie der Substr-Manpage erwähnt. Seufzer
Gerry
Aber passiert dasselbe, wenn die Formularmethode post ist ...?
3lokh
@NikhilGeorge Die hier fragliche Funktion ist strcmp. Es spielt keine Rolle, mit welchen Eingaben verglichen wird.
Ajith
Während der Fehlerbericht besagt, dass es in Ordnung war, null zurückzugeben, ist dies falsch. Alle offiziellen PHP-Versionen von PHP 4.3 bis PHP 7.3 geben von diesen Funktionen nicht null zurück. Ich vermute, es war möglicherweise eine Alpha- oder Beta-Version, und unabhängig davon, ob der geschlossene Fehler ungültig ist oder nicht, wurde er behoben. Weitere Informationen finden Sie unter 3v4l.org/Zq8tM . Dies zeigt, dass HHVM 3.11 - 3.19 davon betroffen ist.
Timo Tijhof
33

Denken Sie immer daran, dass Sie beim Vergleichen von Zeichenfolgen den ===Operator (strikter Vergleich) und nicht den == Operator (loser Vergleich) verwenden sollten.

DataPriest
quelle
8
Eigentlich kann man mit Sicherheit sagen, dass Sie ===beim Vergleich etwas verwenden sollten .
rink.attendant.6
22

Alle Antworten zusammenfassen:

  • ==ist eine schlechte Idee für String-Vergleiche.
    In vielen Fällen erhalten Sie "überraschende" Ergebnisse. Vertraue ihm nicht.

  • === ist in Ordnung und gibt Ihnen die beste Leistung.

  • strcmp() sollte verwendet werden, wenn Sie bestimmen müssen, welche Zeichenfolge "größer" ist, normalerweise für Sortiervorgänge.

Balmipour
quelle
20

Die Verwendung ==kann gefährlich sein.

Beachten Sie, dass die Variable in einen anderen Datentyp umgewandelt wird, wenn sich die beiden unterscheiden.

Beispiele:

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

Wie Sie sehen können, stammen diese beiden von unterschiedlichen Typen, aber das Ergebnis ist true, was möglicherweise nicht das ist, was Ihr Code erwartet.

Die Verwendung ===wird jedoch empfohlen, da der Test zeigt, dass es etwas schneller ist als strcmp()und eine Alternative, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird strcasecmp().

Schnelles Googeln schreit diesen Geschwindigkeitsvergleich: http://snipplr.com/view/758/

Nikola Petkanski
quelle
1
Manchmal werden sie in einen anderen Typ umgewandelt, selbst wenn sie bereits denselben Typ haben.
Antimon
Selbst beim Vergleich zweier Zeichenfolgen, die eine Ganzzahl wie "012" == "12"PHP darstellen, wurde der Typ beider Zeichenfolgen in Ganzzahl geändert 12 == 12und dann zurückgegeben true.
Gehe zum
12

strcmp()und ===beide unterscheiden zwischen Groß- und Kleinschreibung, sind aber ===viel schneller

Beispielcode: http://snipplr.com/view/758/

ungalcrys
quelle
6

strcmp gibt je nach Umgebung unterschiedliche Werte zurück (Linux / Windows)!

Der Grund ist, dass es einen Fehler gibt, da im Fehlerbericht https://bugs.php.net/bug.php?id=53999 steht

Bitte vorsichtig behandeln !! Danke.

kta
quelle
Es wird jedoch immer 0 zurückgegeben, wenn die Zeichenfolgen gleich sind. +1 für die Vorsicht bei anderen Werten als 0.
Prof. Falken Vertrag verletzt
4

Sie können verwenden, strcmp()wenn Sie Zeichenfolgen lexikografisch bestellen / vergleichen möchten . Wenn Sie nur auf Gleichheit prüfen möchten, ==ist dies in Ordnung.

Daniel Egeberg
quelle
1
Wie in usort . In der Tat ist es so ziemlich zum Sortieren gemacht.
Charles
@ Charles Danke. Wikipedia ließ meine Augen glasig werden.
Cbednarski
1
Um das Sortieren klarer zu machen. strcmp () gibt <0 zurück, wenn string1 vor string2 sortiert,> 0, wenn string2 vor string1 sortiert, oder 0, wenn sie identisch sind. Zum Beispiel $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); wird größer als Null zurückgeben, da aaao vor aabo sortiert.
HTML Man
@postfuturist Ich bin sicher, es ist ein Tippfehler und sie meinten ===.
Asche
4

Auch die Funktion kann beim Sortieren helfen. Um das Sortieren klarer zu machen. strcmp () gibt weniger als 0 zurück, wenn string1 vor string2 sortiert, größer als 0, wenn string2 vor string1 sortiert, oder 0, wenn sie gleich sind. Zum Beispiel

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

Die Funktion gibt mehr als Null zurück, da aaao vor aabo sortiert.

HTML Man
quelle
0

PHP Verwenden Sie anstelle der alphabetischen Sortierung den ASCII- Wert des Zeichens, um den Vergleich durchzuführen. Kleinbuchstaben haben einen höheren ASCII- Wert als Großbuchstaben. Es ist besser, den Identitätsoperator === zu verwenden, um diese Art von Vergleich durchzuführen . strcmp () ist eine Funktion zum Durchführen von binären sicheren Zeichenfolgenvergleichen. Es werden zwei Zeichenfolgen als Argumente verwendet und <0 zurückgegeben, wenn str1 kleiner als str2 ist. > 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind. Es gibt auch eine Version ohne Berücksichtigung der Groß- und Kleinschreibung namens strcasecmp () , die Zeichenfolgen zuerst in Kleinbuchstaben konvertiert und dann vergleicht.

Alireza Rahmani Khalili
quelle
0

if ($password === $password2) { ... }Dies ist keine sichere Sache, wenn Sie Kennwörter oder Kennwort-Hashes vergleichen, bei denen eine der Eingaben vom Benutzer gesteuert wird.
In diesem Fall wird ein Timing-Orakel erstellt, mit dem ein Angreifer den tatsächlichen Kennwort-Hash aus Ausführungszeitunterschieden ableiten kann.
Verwenden Sie if (hash_equals($password, $password2)) { ... }stattdessen, da hash_equals einen "Timing Attack Safe String-Vergleich" durchführt.

Ali
quelle