Meine Frage ist:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Ist es möglich, den Aktionscode C nur einmal statt zweimal zu schreiben?
Wie kann man es vereinfachen?
Antworten:
Ihr erster Schritt bei solchen Problemen besteht immer darin, eine Logiktabelle zu erstellen.
Sobald Sie die Tabelle erstellt haben, ist die Lösung klar.
Beachten Sie, dass diese Logik zwar kürzer ist, für zukünftige Programmierer jedoch möglicherweise schwierig beizubehalten ist.
quelle
B
Nebenwirkungen hat, muss die Logiktabelle dies berücksichtigen.A && !B
es sich um ein No-Op handelt:!(A && !B)
Dies entspricht,!A || B
was bedeutet, dass Sieif (!A || B) { /* do action C */ }
einen leeren Block ausführen und vermeiden können.if (A && !B)
es für zukünftige Programmierer wirklich schwierig ist, sie zu warten, gibt es wirklich keine Hilfe für sie.Sie haben zwei Möglichkeiten:
Schreiben Sie eine Funktion, die "Aktion C" ausführt.
Ordnen Sie Ihre Logik neu an, damit Sie nicht so viele verschachtelte if-Anweisungen haben. Fragen Sie sich, unter welchen Bedingungen "Aktion C" auftritt. Es sieht für mich so aus, als ob es passiert, wenn entweder "Bedingung B" wahr oder "Bedingung A" falsch ist. Wir können dies als "NICHT A ODER B" schreiben. Wenn wir dies in C-Code übersetzen, erhalten wir
Um mehr über diese Art von Ausdrücken zu erfahren, schlage ich vor, "Boolesche Algebra", "Prädikatenlogik" und "Prädikatenrechnung" zu googeln. Dies sind tiefe mathematische Themen. Sie müssen nicht alles lernen, nur die Grundlagen.
Sie sollten auch etwas über "Kurzschlussauswertung" lernen. Aus diesem Grund ist die Reihenfolge der Ausdrücke wichtig, um Ihre ursprüngliche Logik genau zu duplizieren. Während dies
B || !A
logisch äquivalent ist, führt die Verwendung als Bedingung "Aktion C" aus, wenn diesB
wahr ist, unabhängig vom Wert vonA
.quelle
...
ist . Wenn es überhaupt nichts ist (dh "mach C, wenn diese Bedingungen erfüllt sind; sonst nichts"), dann ist dies eindeutig die überlegene Lösung, da dieelse
Aussage dann einfach ganz weggelassen werden kann.Sie können die Aussage folgendermaßen vereinfachen:
Andernfalls geben Sie den Code für 'C' in eine separate Funktion ein und rufen Sie ihn auf:
quelle
if (!A || B)
B || !A
wirdtrue
nur dann resultieren, wenn dies derB
true
A
A
und wofürB
steht.In einer Sprache mit Mustervergleich können Sie die Lösung so ausdrücken, dass sie die Wahrheitstabelle in der Antwort von QuestionC direkter widerspiegelt.
Wenn Sie mit der Syntax nicht vertraut sind, wird jedes Muster durch ein | dargestellt gefolgt von den Werten, die mit (a, b) übereinstimmen sollen, und der Unterstrich wird als Platzhalter verwendet, um "alle anderen Werte" zu bedeuten. Da der einzige Fall, in dem wir etwas anderes als Aktion c tun möchten, der Fall ist, in dem a wahr und b falsch ist, geben wir diese Werte explizit als erstes Muster an (wahr, falsch) und tun dann, was in diesem Fall getan werden sollte. In allen anderen Fällen fallen wir zum "Platzhalter" -Muster durch und führen Aktion c aus.
quelle
Die Problemstellung:
beschreibt Implikation : A impliziert B , ein logischer Satz, der äquivalent zu
!A || B
(wie in anderen Antworten erwähnt) ist:quelle
inline
für C undconstexpr
auch für C ++ markieren ?Ugh, das hat mich auch gestolpert, aber wie Code-Apprentice
do action C
betont hatelse
, müssen wir den verschachtelten Block garantiert ausführen oder ausführen , sodass der Code vereinfacht werden kann, um:So treffen wir die 3 Fälle:
do action C
in der Logik Ihrer Frage ist erforderlichcondition A
undcondition B
werdentrue
- In dieser Logik, wenn wir die 2 erreichen nd Begriff in derif
-Anweisung dann wissen wir , dasscondition A
isttrue
also alle müssen wir bewerten ist , dasscondition B
isttrue
else
-Block in Ihrer Logik der Frage erforderlichcondition A
seintrue
undcondition B
zu seinfalse
- der einzige Weg , dass wir das erreichen könnenelse
-Block in dieser Logik würde , wenn seincondition A
warentrue
undcondition B
warenfalse
else
Block in der Logik Ihrer Frage musscondition A
seinfalse
- In dieser Logik, wenncondition A
falsch ist, sind wir auchdo action C
Props an Code-Apprentice, der mich hier rausgebracht hat. Ich würde vorschlagen, seine Antwort zu akzeptieren , da er sie korrekt präsentiert hat, ohne sie zu bearbeiten: /
quelle
B
Wird wegen Kurzschlussauswertung nur ausgewertet, wenn sie!A
falsch ist. Beide müssen also fehlschlagen, um dieelse
Anweisungen auszuführen .!A || B
genau dann falsch, wenn beide!A
undB
falsch sind. DaherA
wird wahr sein, wenn dieelse
ausgeführt wird. Keine Notwendigkeit zur NeubewertungA
.Im Logikkonzept können Sie dieses Problem wie folgt lösen:
Als nachgewiesenes Problem führt dies zu
f = !a + b
. Es gibt einige Möglichkeiten, das Problem zu beweisen, wie z. B. Wahrheitstabelle, Karnaugh Map und so weiter.In C-basierten Sprachen können Sie also Folgendes verwenden:
PS: Karnaugh Map wird auch für kompliziertere Serien von Bedingungen verwendet. Es ist eine Methode zur Vereinfachung von Booleschen Algebra-Ausdrücken.
quelle
Obwohl es bereits gute Antworten gibt, dachte ich, dass dieser Ansatz für jemanden, der neu in der Booleschen Algebra ist, noch intuitiver sein könnte, als eine Wahrheitstabelle auszuwerten.
Als erstes möchten Sie prüfen, unter welchen Bedingungen Sie C ausführen möchten. Dies ist der Fall, wenn
(a & b)
. Auch wenn!a
. Also hast du(a & b) | !a
.Wenn Sie minimieren möchten, können Sie fortfahren. Genau wie bei "normalen" Arithmetiken können Sie multiplizieren.
(a & b) | !a = (a | !a) & (b | !a)
. a | ! a ist immer wahr, Sie können es also einfach streichen, wodurch Sie das minimierte Ergebnis erhalten :b | !a
. Falls die Reihenfolge einen Unterschied macht, weil Sie b nur prüfen möchten, wenn! A wahr ist (zum Beispiel, wenn! A eine Nullzeigerprüfung ist und b eine Operation auf dem Zeiger ist, wie in seinem Kommentar auf @LordFarquaad hingewiesen), könnten Sie dies tun will die beiden wechseln.Der andere Fall (/ * ... * /) wird immer ausgeführt, wenn c nicht ausgeführt wird, also können wir ihn einfach in den else-Fall setzen.
Erwähnenswert ist auch, dass es wahrscheinlich in beiden Fällen sinnvoll ist, Aktion c in eine Methode einzufügen.
Was uns den folgenden Code lässt:
Auf diese Weise können Sie auch Begriffe mit mehr Operanden minimieren, was bei Wahrheitstabellen schnell hässlich wird. Ein weiterer guter Ansatz sind Karnaugh-Karten. Aber ich werde jetzt nicht tiefer darauf eingehen.
quelle
Verwenden Sie boolesche Flags, damit der Code eher wie Text aussieht. Wenn die Logik besonders unklar ist, fügen Sie Kommentare hinzu.
quelle
quelle
Ich würde C zu einer Methode extrahieren und dann die Funktion in allen Fällen so schnell wie möglich beenden.
else
Klauseln mit einer einzigen Sache am Ende sollten nach Möglichkeit fast immer invertiert werden. Hier ist ein schrittweises Beispiel:Auszug C:
Zuerst umkehren
if
, um zuerst loszuwerdenelse
:Zweitens loswerden
else
:Und dann können Sie feststellen, dass die beiden Fälle den gleichen Körper haben und kombiniert werden können:
Optionale Verbesserungsmöglichkeiten wären:
hängt vom Kontext ab, aber wenn
!A || B
es verwirrend ist, extrahieren Sie es in eine oder mehrere Variablen, um die Absicht zu erklärenWelcher
C()
oder welcherD()
nicht außergewöhnliche Fall der letzte ist, sollte der letzte sein. Wenn diesD()
die Ausnahme ist, kehren Sie dasif
letzte Mal umquelle
Die Verwendung von Flags kann dieses Problem ebenfalls lösen
quelle