Ma question est:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Est-il possible d'écrire simplement le code de l'action C une fois au lieu de deux fois?
Comment le simplifier?
Réponses:
Votre première étape dans ce genre de problèmes est toujours de créer une table logique.
Une fois que vous avez fait le tableau, la solution est claire.
Notez que cette logique, bien que plus courte, peut être difficile à maintenir pour les futurs programmeurs.
la source
B
a des effets secondaires, la table logique doit en tenir compte.A && !B
cas où le cas est un no-op:!(A && !B)
est équivalent à!A || B
ce qui signifie que vous pouvez faireif (!A || B) { /* do action C */ }
et éviter un bloc vide.if (A && !B)
c'est vraiment difficile à maintenir pour les futurs programmeurs, alors rien ne les aide.Vous avez deux options:
Écrivez une fonction qui exécute "l'action C".
Réorganisez votre logique afin de ne pas avoir autant d'instructions if imbriquées. Demandez-vous quelles conditions provoquent l '"action C". Il me semble que cela se produit lorsque la "condition B" est vraie ou la "condition A" est fausse. Nous pouvons écrire ceci comme "PAS A OU B". En traduisant cela en code C, nous obtenons
Pour en savoir plus sur ce genre d'expressions, je suggère de googler «algèbre booléenne», «logique des prédicats» et «calcul des prédicats». Ce sont des sujets mathématiques profonds. Vous n'avez pas besoin de tout apprendre, juste les bases.
Vous devriez également vous renseigner sur «l'évaluation des courts-circuits». Pour cette raison, l'ordre des expressions est important pour reproduire exactement votre logique d'origine. Alors que
B || !A
est logiquement équivalent, utiliser ceci comme condition exécutera "l'action C" quandB
est vrai quelle que soit la valeur deA
.la source
...
c'est exactement . Si ce n'est rien du tout (c'est-à-dire «faire C si ces conditions sont remplies; sinon ne rien faire»), alors c'est clairement la meilleure solution, puisque l'else
énoncé peut alors simplement être laissé de côté.Vous pouvez simplifier la déclaration comme ceci:
Sinon, mettez le code pour 'C' dans une fonction séparée et appelez-le:
la source
if (!A || B)
B || !A
ne résulteratrue
que siB
c'est le castrue
, sans réellement vérifier enA
raison d'un court-circuitA
et de ce queB
représente.Dans un langage avec correspondance de modèles, vous pouvez exprimer la solution d'une manière qui reflète plus directement la table de vérité dans la réponse de QuestionC.
Si vous n'êtes pas familier avec la syntaxe, chaque motif est représenté par un | suivi des valeurs à faire correspondre avec (a, b), et le trait de soulignement est utilisé comme caractère générique pour signifier «toutes les autres valeurs». Puisque le seul cas où nous voulons faire autre chose que l'action c est quand a est vrai et b est faux, nous déclarons explicitement ces valeurs comme le premier modèle (vrai, faux) et faisons ensuite tout ce qui doit être fait dans ce cas. Dans tous les autres cas, nous passons au modèle "joker" et faisons l'action c.
la source
L'énoncé du problème:
décrit l' implication : A implique B , une proposition logique équivalente à
!A || B
(comme mentionné dans d'autres réponses):la source
inline
pour C etconstexpr
aussi pour C ++?Ugh, cela m'a fait trébucher aussi, mais comme l'a souligné Code-Apprentice, nous sommes
do action C
sûrs d'avoir besoin ou d'exécuter leelse
bloc imbriqué , ainsi le code pourrait être simplifié pour:Voici comment nous abordons les 3 cas:
do action C
dans la logique de votre question exigecondition A
etcondition B
êtretrue
- Dans cette logique, si nous atteignons le 2 ème terme de laif
déclaration-alors nous savons quecondition A
c'esttrue
donc tout ce que nous devons évaluer c'est quecondition B
c'esttrue
else
-bloc imbriqué dans la logique de votre questioncondition A
devait êtretrue
etcondition B
êtrefalse
- La seule façon d'atteindre leelse
-bloc dans cette logique serait sicondition A
étaienttrue
etcondition B
étaientfalse
else
bloc externe dans la logique de votre question doitcondition A
êtrefalse
- Dans cette logique, sicondition A
est faux, nousdo action C
Props à Code-Apprentice pour me redresser ici. Je suggère d'accepter sa réponse , car il l'a présentée correctement sans la modifier: /
la source
B
ne sera évalué que si!A
est faux. Les deux doivent donc échouer pour exécuter leselse
instructions.!A || B
c'est exactement faux quand les deux!A
etB
sont faux. Par conséquent,A
sera vrai lors de l'else
exécution. Pas besoin de réévaluerA
.Dans le concept logique, vous pouvez résoudre ce problème comme suit:
En tant que problème avéré, il en résulte
f = !a + b
. Il existe quelques moyens de prouver le problème, tels que la table de vérité, la carte de Karnaugh , etc.Donc, dans les langages basés sur C, vous pouvez utiliser comme suit:
PS: Karnaugh Map est également utilisé pour des séries de conditions plus complexes. C'est une méthode de simplification des expressions d'algèbre booléenne.
la source
Même s'il y a déjà de bonnes réponses, j'ai pensé que cette approche pourrait être encore plus intuitive pour quelqu'un qui est nouveau dans l'algèbre booléenne que pour évaluer une table de vérité.
La première chose que vous voulez faire est de regarder, dans quelles conditions vous voulez exécuter C. C'est le cas quand
(a & b)
. Aussi quand!a
. Donc vous avez(a & b) | !a
.Si vous voulez minimiser, vous pouvez continuer. Tout comme dans l'arithmétique "normale", vous pouvez multiplier.
(a & b) | !a = (a | !a) & (b | !a)
. a | ! a est toujours vrai, de sorte que vous pouvez simplement biffer, qui vous laisse avec le résultat réduit:b | !a
. Dans le cas où l'ordre fait une différence, parce que vous voulez vérifier b uniquement si! A est vrai (par exemple quand! A est une vérification de pointeur nul et b est une opération sur le pointeur comme @LordFarquaad l'a souligné dans son commentaire), vous pourriez voulez changer les deux.L'autre cas (/ * ... * /) est sera toujours exécuté lorsque c n'est pas exécuté, donc nous pouvons simplement le mettre dans le cas else.
Il convient également de mentionner qu'il est probablement logique de mettre l'action c dans une méthode.
Ce qui nous laisse avec le code suivant:
De cette façon, vous pouvez également minimiser les termes avec plus d'opérandes, ce qui devient rapidement laid avec les tables de vérité. Les cartes de Karnaugh sont une autre bonne approche. Mais je ne vais pas approfondir cela maintenant.
la source
Pour que le code ressemble plus à du texte, utilisez des indicateurs booléens. Si la logique est particulièrement obscure, ajoutez des commentaires.
la source
la source
Je voudrais extraire C dans une méthode, puis quitter la fonction dès que possible dans tous les cas.
else
les clauses avec une seule chose à la fin devraient presque toujours être inversées si possible. Voici un exemple étape par étape:Extrait C:
Inversez d'abord
if
pour vous débarrasser deelse
:Débarrassez-vous du second
else
:Et puis vous pouvez remarquer que les deux boîtiers ont le même corps et peuvent être combinés:
Les choses facultatives à améliorer seraient:
dépend du contexte, mais si cela
!A || B
prête à confusion, extrayez-le dans une ou plusieurs variables pour expliquer l'intentionquel que
C()
soitD()
le cas non exceptionnel ou le cas non exceptionnel qui doit passer en dernier, siD()
c'est l'exception, alors inversez leif
dernière foisla source
L'utilisation d'indicateurs peut également résoudre ce problème
la source