Perbandingan string menggunakan '==' vs. 'strcmp ()'

334

Tampaknya ===operator PHP peka terhadap huruf besar-kecil. Jadi adakah alasan untuk menggunakannya strcmp()?

Apakah aman melakukan hal seperti berikut ini?

if ($password === $password2) { ... }
Jiew Meng
sumber
10
Apa kaitan sensitivitas huruf dengan strcmp?
kennytm
1
@ KennyTM: strcmpcase-sensitive. Dalam beberapa bahasa, seperti VB, perbandingan string mungkin tidak, dan dengan demikian akan menghasilkan hasil yang berbeda. Ini bukan kasus di PHP.
cHao
13
@jie: Anda mungkin ingin menggunakan ===bukan ==karena '0XAB' == '0xab'itu benar.
kennytm
17
menggunakan === daripada == adalah penting, karena membandingkan string apa pun dengan 0 dengan == akan mengembalikan true yang jelas salah ...
Karl Adler
4
@Kenny Also '0xAB' == '171'
Antimony

Jawaban:

329

Alasan menggunakannya adalah karena strcmp

mengembalikan <0 jika str1 kurang dari str2; > 0 jika str1 lebih besar dari str2, dan 0 jika keduanya sama.

===hanya mengembalikan trueatau false, itu tidak memberi tahu Anda yang merupakan string "lebih besar".

tipuan
sumber
9
icic tho dalam kasus saya saat ini, saya tidak perlu tahu string mana yang lebih besar :)
Jiew Meng
155
strcmp dengan string yang cocok butuh 0,207852 detik strcmp dengan string yang tidak cocok butuh 0,215276 detik === dengan string yang cocok butuh 0,067122 detik === dengan string yang tidak cocok, butuh waktu 0,057305 detik snipplr.com/view/758
3
Penggunaan lain untuk strcmp itu menunjukkan penyortiran. Untuk lebih jelas tentang penyortiran. strcmp () mengembalikan <0 jika string1 diurutkan sebelum string2,> 0 jika string2 diurutkan sebelum string1 atau 0 jika mereka sama. Misalnya $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); akan kembali lebih besar dari nol, karena aaao sedang menyortir sebelum aabo.
HTML Man
20
Mengapa jawaban ini mendapatkan hasil maksimal? Saya downvoting karena meskipun itu adalah jawaban yang pantas untuk pertanyaan ini tetapi bukan jawaban yang 'benar'. Jawaban yang benar harus 'Gunakan ===' karena banyak orang sudah mengatakan dalam jawaban lain.
onur güngör
2
Güngör @onur Sebenarnya, ini tidak jawaban pertanyaan op, yang merupakan So is there any reason to use strcmp() ?, sementara jawaban Postfuturist ini tidak. Oh, neraka ... tidak ada jawaban satu tampaknya mengkompilasi sekaligus penggunaan dari strcmp(), yang kinerja dari ===, dan keandalan buruk dari ==untuk perbandingan string ... jadi saya menambahkan tambang ke dalam daftar.
Balmipour
222

Anda tidak boleh menggunakan ==untuk perbandingan string. ===tidak apa-apa.

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

Jalankan saja kode di atas dan Anda akan melihat alasannya.

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

Nah, itu sedikit lebih baik.

postfuturist
sumber
19
== bukan hanya masalah untuk jenis yang berbeda. Terkadang akan memberikan hasil yang tidak terduga bahkan jika kedua belah pihak adalah string. Coba '1e3' == '1000'
Antimony
3
bagaimana 0 == 'password123'?
Andy Lobel
24
@AndyLobel PHP memaksa 'password123' ke nomor menggunakan aturan perbandingan longgar yang aneh karena operan lainnya adalah angka, string itu, seperti kebanyakan, memaksa ke angka 0, dan PHP mengembalikan true untuk perbandingan.
postfuturist
8
Var_dump ((int) 'password123') cepat; membantu saya sepenuhnya memahami mengapa ini terjadi ... ** malu ** ... Saya sangat suka operator ===
Carlton
3
ini karena menggunakan '==' jika salah satu dari dua operan dapat dicetak ke angka, php melempar kedua operan ke angka, dan lebih banyak lagi, jika string bukan angka dilemparkan ke angka, dibutuhkan nilai nol, menghasilkan nilai nol, menghasilkan sama dengan nol, jadi hasil perbandingan dengan sederhana '==' dapat sesuatu yang tidak diinginkan
Luca C.
98

Jangan gunakan ==dalam PHP. Itu tidak akan melakukan apa yang Anda harapkan. Bahkan jika Anda membandingkan string dengan string, PHP secara implisit akan melemparkannya ke float dan melakukan perbandingan numerik jika ditampilkan secara numerik.

Misalnya '1e3' == '1000'mengembalikan true. Anda harus menggunakannya ===sebagai gantinya.

Antimon
sumber
16
Tapi Anda bisa ===.
Roman Newaza
11
@Roman ya tapi banyak programmer PHP tidak tahu mereka harus melakukan itu. Karena itu peringatan.
Antimony
5
@Antimony Jadi mengapa tidak memberi tahu mereka apa yang harus mereka lakukan dalam jawaban Anda?
Tim
43

Yah..menurut laporan bug php ini , Anda bahkan bisa mendapatkan 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.';
    }
 ?>

Ini memberi Anda peringatan, tetapi masih melewati perbandingan.
Anda seharusnya melakukan ===seperti yang disarankan oleh @postfuturist.

Ajith
sumber
5
Wow +1. Kutipan dari tautan: "Perilaku yang ditetapkan untuk fungsi yang menerima jenis argumen yang salah untuk mengembalikan nol". Itu luar biasa mengingat manual hanya mengatakan ini: "Mengembalikan <0 jika str1 kurang dari str2;> 0 jika str1 lebih besar dari str2, dan 0 jika mereka sama". Null tidak disebutkan sebagai suatu kemungkinan, namun pada halaman-halaman seperti halaman manual substr disebutkan. desah
Gerry
Tetapi apakah hal yang sama terjadi ketika metode formulir dikirim ...?
3lokh
@NikhilGeorge Tidak, fungsi yang dimaksud di sini adalah strcmp. Tidak masalah input mana yang dibandingkan.
Ajith
Meskipun laporan bug mengatakan tidak masalah untuk mengembalikan nol, ini tidak benar. Semua rilis PHP resmi dari PHP 4.3 ke PHP 7.3 tidak menghasilkan null dari fungsi-fungsi ini. Saya menduga itu mungkin merupakan rilis alfa atau beta, dan terlepas dari bug yang ditutup tidak valid, itu diperbaiki. Lihat 3v4l.org/Zq8tM untuk detail, yang menunjukkan bahwa hal itu memengaruhi HHVM 3.11 - 3.19.
Timo Tijhof
33

Selalu ingat, saat membandingkan string, Anda harus menggunakan ===operator (perbandingan ketat) dan bukan == operator (perbandingan longgar).

DataPriest
sumber
8
Sebenarnya, saya pikir aman untuk mengatakan bahwa Anda harus menggunakan ===ketika membandingkan sesuatu .
rink.attendant.6
22

Ringkas semua jawaban:

  • ==adalah ide buruk untuk perbandingan string.
    Ini akan memberi Anda hasil "mengejutkan" dalam banyak kasus. Jangan percaya itu.

  • === baik-baik saja, dan akan memberi Anda kinerja terbaik.

  • strcmp() harus digunakan jika Anda perlu menentukan string mana yang "lebih besar", biasanya untuk operasi penyortiran.

Balmipour
sumber
20

Menggunakan ==mungkin berbahaya.

Catatan, itu akan melemparkan variabel ke tipe data lain jika keduanya berbeda.

Contoh:

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

Seperti yang Anda lihat, keduanya berasal dari jenis yang berbeda, tetapi hasilnya adalah true , yang mungkin bukan apa yang diharapkan oleh kode Anda.

Menggunakan ===, bagaimanapun, direkomendasikan sebagai acara uji bahwa itu sedikit lebih cepat dari strcmp()dan alternatif case-sensitive-nyastrcasecmp() .

Googling cepat berteriak perbandingan kecepatan ini: http://snipplr.com/view/758/

Nikola Petkanski
sumber
1
Kadang-kadang itu melemparkan mereka ke tipe yang berbeda bahkan jika mereka sudah memiliki tipe yang sama.
Antimony
bahkan ketika membandingkan dua string yang mewakili integer seperti "012" == "12"php mengubah tipe kedua string menjadi integer 12 == 12dan kemudian dikembalikan true.
GoTo
12

strcmp()dan ===keduanya case sensitif tetapi=== jauh lebih cepat

kode sampel: http://snipplr.com/view/758/

ungalcrys
sumber
6

strcmp akan mengembalikan nilai yang berbeda berdasarkan lingkungan yang dijalankannya (Linux / Windows)!

Alasannya adalah bahwa ia memiliki bug seperti laporan bug mengatakan https://bugs.php.net/bug.php?id=53999

Tolong tangani dengan hati-hati !! Terima kasih.

kta
sumber
Akan selalu mengembalikan 0 jika senarnya sama. +1 untuk berhati-hati dalam merawat nilai selain 0.
Kontrak Prof. Falken dilanggar
4

Anda dapat menggunakan strcmp()jika Anda ingin memesan / membandingkan string secara leksikografis . Jika Anda hanya ingin memeriksa kesetaraan maka ==tidak apa-apa.

Daniel Egeberg
sumber
1
Seperti di usort . Bahkan, itu cukup banyak dibuat untuk menyortir.
Charles
@ Charles Terima kasih. Wikipedia membuat mata saya berkaca-kaca.
cbednarski
1
Untuk lebih jelas tentang penyortiran. strcmp () mengembalikan <0 jika string1 diurutkan sebelum string2,> 0 jika string2 diurutkan sebelum string1 atau 0 jika mereka sama. Misalnya $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); akan kembali lebih besar dari nol, karena aaao sedang menyortir sebelum aabo.
HTML Man
@ postfuturist Saya yakin ini salah ketik dan artinya ===.
ash
4

Juga Fungsi ini dapat membantu dalam penyortiran. Untuk lebih jelas tentang penyortiran. strcmp () mengembalikan kurang dari 0 jika string1 diurutkan sebelum string2, lebih besar dari 0 jika string2 diurutkan sebelum string1 atau 0 jika mereka sama. Sebagai contoh

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

Fungsi akan kembali lebih besar dari nol, karena aaao sedang mengurutkan sebelum aabo.

HTML Man
sumber
0

PHP Alih-alih menggunakan pengurutan alfabet, gunakan nilai ASCII karakter untuk membuat perbandingan. Huruf kecil memiliki nilai ASCII lebih tinggi daripada huruf kapital. Lebih baik menggunakan operator identitas === untuk membuat perbandingan semacam ini. strcmp () adalah fungsi untuk melakukan perbandingan string aman biner. Dibutuhkan dua string sebagai argumen dan mengembalikan <0 jika str1 kurang dari str2; > 0 jika str1 lebih besar dari str2, dan 0 jika keduanya sama. Ada juga versi case-insensitive bernama strcasecmp () yang pertama-tama mengubah string menjadi huruf kecil dan kemudian membandingkannya.

Alireza Rahmani Khalili
sumber
0

if ($password === $password2) { ... }bukanlah hal yang aman untuk dilakukan ketika membandingkan kata sandi atau hash kata sandi di mana salah satu input dikendalikan oleh pengguna.
Dalam hal ini ia menciptakan waktu oracle yang memungkinkan penyerang untuk mendapatkan hash kata sandi yang sebenarnya dari perbedaan waktu eksekusi.
Gunakan if (hash_equals($password, $password2)) { ... }sebagai gantinya, karena hash_equals melakukan "perbandingan waktu serangan tali aman".

Ali
sumber