2008-09-30 8 views

Répondre

80

Il est plus utile pour les boucles que pour les instructions.

while(var = GetNext()) 
{ 
    ...do something with var 
} 

qui autrement aurait à écrire

var = GetNext(); 
while(var) 
{ 
...do something 
var = GetNext(); 
} 
+8

Je suis d'accord - mais j'écrirais: while ((var = GetNext())! = 0) {...} sans y penser à deux fois, en partie parce que GCC se plaint si je ne le fais pas avec mes options de compilation par défaut . –

+1

True. En supposant que vous utilisez un langage qui supporte les déclarations en boucle, et que vous n'utilisez pas déjà var en dehors de la boucle. – Gerald

+0

dans certaines langues, comme ANSI C, les règles de portée ne permettent pas cette approche, @KerrekSB – wirrbel

22

Il peut être utile si vous appelez une fonction qui renvoie soit des données pour travailler sur ou un drapeau pour indiquer une erreur (ou que vous avez terminé).

Quelque chose comme:

while ((c = getchar()) != EOF) { 
    // process the character 
} 

// end of file reached... 

Personnellement c'est un idiome que je ne suis pas extrêmement friand, mais parfois l'alternative est plus laid.

28

Il est plus utile si vous appelez une fonction:

if (n = foo()) 
{ 
    /* foo returned a non-zero value, do something with the return value */ 
} else { 
    /* foo returned zero, do something else */ 
} 

Bien sûr, vous pouvez simplement mettre le n = foo(); sur une déclaration séparée alors si (n), mais je pense que ce qui précède est un idiome assez lisible.

+0

Je pense que vous devriez le placer entre parenthèses ou gcc se plaindra avec: avertissement: suggérez entre parenthèses autour de l'affectation utilisée comme valeur de vérité [-Wparentheses] Comme ceci: if ((n = foo())) { // faire quelque chose avec la valeur de retour } else { // foo retourné zéro/NULL, faire autre chose } –

8

L'idiome est plus utile lorsque vous écrivez une boucle while au lieu d'une instruction if. Pour une instruction if, vous pouvez la décomposer comme vous l'avez décrit. Mais sans cette construction, vous devez soit vous répéter:

c = getchar(); 
while (c != EOF) { 
    // ... 
    c = getchar(); 
} 

ou utiliser une structure en boucle et demi:

while (true) { 
    c = getchar(); 
    if (c == EOF) break; 
    // ... 
} 

Je préfère habituellement la boucle et-a- demi forme.

8

GCC peut vous aider à détecter (avec -Wall) si vous essayez involontairement d'utiliser une assignation en tant que valeur de la vérité, dans le cas où il vous recommande d'écrire

if ((n = foo())) { 
    ... 
} 

à savoir utilisez des parenthèses supplémentaires pour indiquer que c'est vraiment ce que vous voulez.

3

En PHP, par exemple, il est utile pour une boucle à travers les résultats de la base de données SQL:

while ($row = mysql_fetch_assoc($result)) { 
    // Display row 
} 

Cela ressemble beaucoup mieux que:

$row = mysql_fetch_assoc($result); 
while ($row) { 
    // Display row 
    $row = mysql_fetch_assoc($result); 
} 
+3

Cela a aussi l'effet secondaire de $ row ne vivant pas au-delà de cette boucle et donc éligible pour la collecte des ordures plus tôt (dans les langues qui font GC de toute façon). –

23

Je trouve cela très utile dans les chaînes d'actions qui impliquent souvent la détection d'erreurs, etc.

if ((rc = first_check(arg1, arg2)) != 0) 
{ 
    report error based on rc 
} 
else if ((rc = second_check(arg2, arg3)) != 0) 
{ 
    report error based on new rc 
} 
else if ((rc = third_check(arg3, arg4)) != 0) 
{ 
    report error based on new rc 
} 
else 
{ 
    do what you really wanted to do 
} 

L'alternative (ne pas utiliser l'affectation dans l'état) est:

rc = first_check(arg1, arg2); 
if (rc != 0) 
{ 
    report error based on rc 
} 
else 
{ 
    rc = second_check(arg2, arg3); 
    if (rc != 0) 
    { 
     report error based on new rc 
    } 
    else 
    { 
     rc = third_check(arg3, arg4); 
     if (rc != 0) 
     { 
      report error based on new rc 
     } 
     else 
     { 
      do what you really wanted to do 
     } 
    } 
} 

Avec vérification d'erreur prolongée, l'alternative peut ruisseler l'ERS de la page alors que la cession en conditionnelle Version ne fait pas ça.

+0

Oui, je l'ai fait juste pour éviter une imbrication excessive et j'ai ensuite cherché en ligne pour voir si c'était une pratique courante. En fin de compte, j'ai décidé de ne pas le faire parce que je n'avais en fait qu'un seul cas, mais cela semble être une raison légitime de mettre la tâche dans cette condition. – Ibrahim

+0

Vos collègues détestent! Pour moi, au moins dans la plupart des cas, est beaucoup plus facile à maintenir qu'un arbre géant ou de nombreux retours. Je préfère le retour simple d'une fonction ... – Nathan

3

La réponse courte est que Expression-oriented les langages de programmation permettent un code plus succinct. Le ne vous force pas à separate commands from queries.

+0

C'est un combat constant pour imposer le codage sans affectations dans if(), while(), et d'autres instructions similaires. C/C++ sont connus pour leurs effets secondaires qui s'avèrent souvent être des bugs, surtout quand on ajoute les opérateurs ++ et -. –

2

L'autre avantage vient pendant l'utilisation de gdb. Dans le code suivant, le code d'erreur n'est pas connu si nous devions effectuer une seule étape.

while (checkstatus() != -1) { 
    // process 
} 

plutôt

while (true) { 
    int error = checkstatus(); 
    if (error != -1) 
     // process 
    else 
     //fail 
} 

Maintenant, lors de l'étape unique, nous pouvons savoir ce qui était le code d'erreur de retour de la checkStatus().

-2

La raison en est:

  1. Amélioration de la performance (parfois)

  2. code Lesser (toujours)

Prenons un exemple: Il existe une méthode someMethod() et dans un if condition que vous voulez vérifier si la valeur de retour de la méthode est null. Sinon, vous allez utiliser la valeur de retour à nouveau.

If(null != someMethod()){ 
    String s = someMethod(); 
    ...... 
    //Use s 
} 

Cela entravera les performances car vous appelez deux fois la même méthode. Au lieu d'utiliser:

String s; 
If(null != (s = someMethod())) { 
    ...... 
    //Use s 
} 
Questions connexes