Comparação de string usando '==' vs. 'strcmp ()'

334

Parece que o ===operador do PHP diferencia maiúsculas de minúsculas. Então, há uma razão para usar strcmp()?

É seguro fazer algo como o seguinte?

if ($password === $password2) { ... }
Jiew Meng
fonte
10
O que diferencia maiúsculas de minúsculas tem a ver strcmp?
Kennytm
11
@KennyTM: diferencia strcmpmaiúsculas de minúsculas. Em alguns idiomas, como VB, a comparação de cadeias pode não ser e, portanto, retornaria um resultado diferente. Este não é o caso em PHP, no entanto.
cHao 26/07/10
13
@ jie: Você pode querer usar em ===vez de ==porque '0XAB' == '0xab'é verdade.
Kennytm 26/07/10
17
para uso === em vez de == é importante, porque comparando qualquer seqüência a 0 com == retornará true que é obviamente falso ...
Karl Adler
4
@Kenny Also '0xAB' == '171'
Antimony

Respostas:

329

A razão para usá-lo é porque strcmp

retorna <0 se str1 for menor que str2; > 0 se str1 for maior que str2 e 0 se forem iguais.

===apenas retorna trueou false, não informa qual é a string "maior".

deceze
fonte
9
ICIC tho no meu caso atual, eu não preciso saber que a corda é maior :)
Jiew Meng
154
strcmp com strings correspondentes levou 0,207852 segundos strcmp com strings não correspondentes levou 0,215276 segundos === com strings correspondentes levou 0,067122 segundos === com strings não correspondentes levou 0,057305 segundos snipplr.com/view/758
3
O outro uso para strcmp mostra a classificação. Para ser mais claro sobre a classificação. strcmp () retorna <0 se string1 classifica antes de string2,> 0 se string2 classifica antes de string1 ou 0 se eles são iguais. Por exemplo $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); retornará maior que zero, pois aaao está ordenando antes de aabo.
HTML Man
20
Por que essa resposta recebe mais votos positivos? Estou com voto negativo porque, embora seja a resposta que essa pergunta merece, mas não a resposta 'certa'. A resposta correta deve ser 'Use ===', como muitas pessoas já disseram em outras respostas.
onur güngör
2
@onur Güngör Na verdade, isso faz respostas à pergunta do op, que é So is there any reason to use strcmp() ?, ao mesmo tempo resposta de Postfuturist não. Oh, inferno ... nenhuma resposta um parecia compilar ao mesmo tempo o uso de strcmp(), o desempenho de ===, e o mau confiabilidade das ==comparações de string ... então eu adicionei meu para a lista.
Balmipour 31/08/19
222

Você nunca deve usar ==para comparação de cadeias. ===está bem.

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

Basta executar o código acima e você verá o porquê.

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

Agora, isso é um pouco melhor.

pós-futebolista
fonte
19
== não é apenas um problema para diferentes tipos. Às vezes, produz resultados inesperados, mesmo que os dois lados sejam uma string. Tente '1e3' == '1000'
Antimony
3
como 0 == 'password123'?
Andy Lobel
24
O @AndyLobel PHP restringe 'password123' a um número usando suas estranhas regras de comparação, uma vez que o outro operando é um número, essa string, como a maioria, restringe o número 0, e o PHP retorna verdadeiro para a comparação.
postfuturist
8
Um rápido var_dump ((int) 'password123'); me ajudou a compreender por que isso aconteceu ... ** envergonhado ** ... Eu realmente gosto do === operador
Carlton
3
isso é porque use '==' se um dos dois operandos puder ser convertido em número, o php converterá ambos os operandos em números e, mais ainda, se uma string não numérica for convertida em número, ela assume o valor zero, resultando igual a zero, de modo que o resultado da comparação com um simples '==' lata algo indesejado
Luca C.
98

Não use ==em PHP. Não fará o que você espera. Mesmo se você estiver comparando strings com strings, o PHP implicitamente as converterá em floats e fará uma comparação numérica se elas aparecerem numéricas.

Por exemplo, '1e3' == '1000'retorna true. Você deve usar em seu ===lugar.

Antimônio
fonte
16
Mas você pode apenas ===.
Roman Newaza 25/01
11
@ Roman Sim, mas muitos programadores de PHP não sabem que precisam fazer isso. Daí o aviso.
Antimônio
5
@ Anttimony Então, por que não dizer a eles o que eles devem fazer na sua resposta?
Tim
43

Bem ... de acordo com este relatório de erros do php , você pode até receber 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.';
    }
 ?>

Emite um aviso, mas ainda ignora a comparação.
Você deveria estar ===seguindo o @postfuturist sugerido.

Ajith
fonte
5
Uau +1. Cite no link: "Foi estabelecido um comportamento para a função que recebe o tipo errado de argumento (s) para retornar nulo". Isso é incrível, considerando que o manual apenas diz o seguinte: "Retorna <0 se str1 for menor que str2;> 0 se str1 for maior que str2 e 0 se forem iguais". Nulo não é mencionado como uma possibilidade, mas em páginas como a página de manual substr é mencionado. sigh
Gerry
Mas o mesmo acontece quando o método do formulário é publicado ...?
3lokh
@NikhilGeorge Sim, a função em questão aqui é strcmp. Não importa quais entradas estão sendo comparadas.
quer
Enquanto o relatório de erro diz que não há problema em retornar nulo, isso está incorreto. Todas as versões oficiais do PHP do PHP 4.3 ao PHP 7.3 não retornam nulo a partir dessas funções. Suspeito que possa ter sido uma versão alfa ou beta e, independentemente de o bug estar fechado é inválido, foi corrigido. Consulte 3v4l.org/Zq8tM para obter detalhes, que mostram que isso afeta o HHVM 3.11 - 3.19.
Timo Tijhof
33

Lembre-se sempre de que, ao comparar strings, você deve usar o ===operador (comparação estrita) e não o == operador (comparação livre).

DataPriest
fonte
8
Na verdade, acho seguro dizer que você deve usar ===ao comparar qualquer coisa .
usar o seguinte código
22

Resumindo todas as respostas:

  • ==é uma má ideia para comparações de strings.
    Isso lhe dará resultados "surpreendentes" em muitos casos. Não confie nisso.

  • === está bem e fornecerá o melhor desempenho.

  • strcmp() deve ser usado se você precisar determinar qual sequência é "maior", normalmente para operações de classificação.

Balmipour
fonte
20

Usar ==pode ser perigoso.

Observe que ele converteria a variável para outro tipo de dados se os dois diferissem.

Exemplos:

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

Como você pode ver, esses dois são de tipos diferentes, mas o resultado é trueque pode não ser o que seu código espera.

Usando ===, no entanto, é recomendado como teste revela que ele é um pouco mais rápido do que strcmp()e sua alternativa case-insensitive strcasecmp().

Pesquisa rápida grita esta comparação de velocidade: http://snipplr.com/view/758/

Nikola Petkanski
fonte
11
Às vezes, as projeta para um tipo diferente, mesmo que já tenham o mesmo tipo.
Antimony
mesmo quando comparamos duas strings que representavam um número inteiro como "012" == "12"php, alteramos o tipo de ambas as strings para inteiro 12 == 12e depois retornamos true.
GoTo 23/09
12

strcmp()e ===diferenciam maiúsculas de minúsculas, mas ===é muito mais rápido

código de exemplo: http://snipplr.com/view/758/

ungalcrys
fonte
6

O strcmp retornará valores diferentes com base no ambiente em execução (Linux / Windows)!

O motivo é que ele possui um bug, como diz o relatório https://bugs.php.net/bug.php?id=53999

Por favor, manuseie com cuidado !! Obrigado.

kta
fonte
Ele sempre retornará 0 se as seqüências de caracteres forem iguais. +1 por ter cuidado com qualquer outro valor que não 0.
O contrato do Prof. Falken violou
4

Você pode usar strcmp()se desejar solicitar / comparar seqüências lexicograficamente . Se você apenas deseja verificar a igualdade, ==está tudo bem.

Daniel Egeberg
fonte
11
Como em usort . De fato, é praticamente feito para classificação.
Charles
@ Charles Obrigado. A Wikipedia fez meus olhos brilharem.
cbednarski
11
Para ser mais claro sobre a classificação. strcmp () retorna <0 se string1 classifica antes de string2,> 0 se string2 classifica antes de string1 ou 0 se eles são iguais. Por exemplo $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); retornará maior que zero, pois aaao está ordenando antes de aabo.
HTML Man
@postfuturist Tenho certeza que é um erro de digitação e eles quiseram dizer ===.
cinza
4

A função também pode ajudar na classificação. Para ser mais claro sobre a classificação. strcmp () retorna menos que 0 se a string1 classificar antes da string2, maior que 0 se a string2 classificar antes da string1 ou 0 se forem iguais. Por exemplo

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

A função retornará maior que zero, pois aaao está ordenando antes de aabo.

Homem HTML
fonte
0

PHP Em vez de usar a classificação alfabética, use o valor ASCII do caractere para fazer a comparação. Letras minúsculas têm um valor ASCII mais alto que maiúsculas. É melhor usar o operador de identidade === para fazer esse tipo de comparação. strcmp () é uma função para realizar comparações seguras binárias de strings. Ele usa duas strings como argumentos e retorna <0 se str1 for menor que str2; > 0 se str1 for maior que str2 e 0 se forem iguais. Há também uma versão que não diferencia maiúsculas de minúsculas chamada strcasecmp () que primeiro converte as seqüências de caracteres em minúsculas e as compara.

Alireza Rahmani Khalili
fonte
0

if ($password === $password2) { ... }não é uma coisa segura a fazer quando se compara senhas ou hashes de senha em que uma das entradas é controlada pelo usuário.
Nesse caso, ele cria um oráculo de tempo, permitindo que um invasor obtenha o hash da senha real das diferenças de tempo de execução.
Use em if (hash_equals($password, $password2)) { ... }vez disso, porque hash_equals executa "comparação segura de seqüência de caracteres do ataque de tempo".

Todos
fonte