web-dev-qa-db-fra.com

Opérateurs "égaux à" ou "non égaux à" dans une instruction if-else

Lorsque vous écrivez des énoncés if-else en C, existe-t-il une raison pour laquelle on utiliserait préférentiellement l'opérateur "égal à" sur "pas", alors que les deux peuvent produire le même résultat?

Le code ci-dessous fournit un contexte. Dans ce cas, si le nombre d'arguments est égal à 2, une chaîne sera extraite de l'utilisateur. Cependant, si une autre valeur d'arguments est obtenue, un message d'erreur apparaîtra.

int main(int argc, string argv[])
{
    string msg;

    if (argc == 2) 
    {
        msg = GetString();
    }
    else
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }

Cependant, je peux obtenir exactement le même résultat que ci-dessus en modifiant la condition de la boucle if-else en "pas égal à" et en retournant les actions associées. Voir ci-dessous:

int main(int argc, string argv[])
{
    string msg;

    if (argc != 2) 
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }
    else
    {
        msg = GetString();
    }

Quoi qu'il en soit, étant donné que les deux aboutissent au même résultat, faut-il utiliser l'un préférentiellement par rapport à l'autre? 

17
user7011119

Il y a une raison technique en C++, car si vous avez l'habitude d'utiliser == sur !=, vous n'aurez pas à surcharger autant d'opérateurs. 

Ceci est important lorsque vous traitez avec des objets de fonction ("foncteurs"). Par exemple, lorsque vous utilisez une classe de conteneur standard pour stocker vos propres objets personnalisés et que vous souhaitez les trier automatiquement. Pour que l’objet fonction (par exemple, std :: equal_to) fonctionne, votre classe doit surcharger l’opérateur == uniquement. Vous n'avez pas à surcharger == et != tous les deux.

De la même manière, d'autres objets fonction exigent que vous surchargiez < et non pas tous < > == != <= >=.


Généralement, les négations ne sont pas faciles à comprendre pour le cerveau humain. Surtout si vous avez des doubles négations. Dans la plupart des langages de programmation, il est coutume d'écrire le contrôle d'égalité en premier, si l'ordre n'a pas d'importance technique. Le plus souvent, cela rend le code plus facile à lire.

Mais comme souvent avec le style de programmation et de codage, il n'y a pas de règles noires ou blanches. Si la vérification a pour but de rechercher une erreur, la méthode la plus lisible pour écrire le traitement des erreurs a la priorité sur "Les humains trouvent les négations plus difficiles à lire".

Considérez ce code pas trop bien écrit:

if(input == good)
{
  if(format == expected)
  {
    do_stuff();
    return ok;
  }
  else
  {
    return error_format;
  }
}
else
{
  return error_input;
}

Imaginez que nous devions ajouter encore plus de traitement des erreurs à cela. Cas assez courant: supposons que nous écrivions un analyseur syntaxique ou un décodeur de protocole de données avec beaucoup de traitement des erreurs. Les multiples niveaux d'accolades imbriquées allaient bientôt transformer le code en désordre complet. 

Nous pouvons nous débarrasser de la nécessité d'avoir des instructions if imbriquées si nous passons de == à! =.

if(input != good)
{
  return error_input;
}

if(format != expected)
{
  return error_format;
}

// if we got here then all is well
do_stuff();
return ok;

Cela sera beaucoup plus lisible et évoluera bien si nous devons ajouter plus de contrôles d'erreur. Donc en changeant en! = Nous avons rendu le code plus lisible.

12
Lundin

C'est juste un problème de style de codage. Je déteste imbriquer la logique principale, je vais l'écrire ainsi:

int main(int argc, string argv[])
{
    if (argc != 2) 
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }

    string msg = GetString();
}

BTW: La signature de main devrait être int main(int argc, char *argv[]).

12
songyuanyao

Je préfère généralement "égal à", car cela rend le code plus "lisible" pour un humain. Cela simplifie le code. Il s'agirait plus d'une "règle de codage de Nice" que d'une "règle" car elle n'a aucun impact sur le temps d'exécution (elle faisait partie des directives de codage de ma société précédente).

Vérifie ça:

if ( !isEmpty() )

Votre cerveau mettra quelques millisecondes de plus à comprendre le résultat du test que si vous écrivez:

if ( isEmpty() )

Même si cela n'a aucun impact sur l'exécution, je préfère généralement "est égal" à "n'est pas égal".

Les mêmes arguments vont aux variables et aux noms de fonction. Préférer l'attribut/la méthode isSet à la place de isNotSet. Lire un code tel que if ( !isNotSet() ) est plus facile que si if ( isSet() ), même s’ils sont équivalents à la fin.

Si vous utilisez du code sur lequel vous n'avez aucun contrôle et que celui-ci fournit à un membre répondant à une question négative, alors:

if ( isNotSet() )

est certainement plus facile à lire pour un développeur que:

if ( !isNotSet() )
5
jpo38

Comme d'autres l'ont dit, c'est un problème de style. Il n'y a pas de réelle différence. 

Une chose à garder à l'esprit, cependant, est d'essayer d'être cohérent. Si vous avez un bloc vérifiant si value1 == 2, essayez de ne pas vérifier le prochain bloc value2 != 4. Le seul mauvais style est le style incohérent.

1
technokrat

De nos jours, il n'y a pas de différence sémantique entre les deux cas, car même l'optimisation plus simple appliquée par les compilateurs pourrait perturber le " flux d'exécution prévu ".

Il y a peut-être 30 ou 40 ans, il y aurait peut-être eu une différence entre les deux choix, alors que l'étape de génération de code du compilateur C était plutôt conforme au code écrit.

La différence actuelle réside dans la clarté de la syntaxe et du style.

Donc, en écrivant

while( *dst++=*src++ );

de nos jours pourrait générer le même code machine que

for( i=0; src[i] != 0; i++ )
  dst[i] = src[i];
dst[i] = '\0';

Ces derniers pourraient en général être beaucoup plus faciles à lire, comme le montre

if( ! isOK() )
  dontDoIt();
else
  doIt();

et en

if( isOK() )
  doIt()
else
  dontDoIt();

Mais soyez assuré que la "clarté" n'est pas une valeur absolue: elle ne dépend pas seulement des "compétences en matière de programmation et du goût" des lecteurs/relecteurs, mais également du code lui-même.

En bout de ligne: faites votre choix et respectez-le pour l’uniformité!

0
EnzoR

C'est une question de conception de programme. En tant que programmeur, vous devez choisir le meilleur flux pour l'exécution, la maintenance, la lisibilité et les performances. De plus, ce sont deux déclarations complètement différentes. Si vous voulez que votre fonction appelle UNIQUEMENT lorsque argc est égal à 2 par rapport à CallString (); chaque fois que le nombre n'est pas 2. 

0
William D. Wells