Moje pytanie brzmi:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Czy można po prostu napisać kod akcji C raz zamiast dwa razy?
Jak to uprościć?
Odpowiedzi:
Pierwszym krokiem w tego rodzaju problemach jest zawsze utworzenie tablicy logicznej.
Po przygotowaniu stołu rozwiązanie jest jasne.
Zwróć uwagę, że ta logika, choć krótsza, może być trudna do utrzymania dla przyszłych programistów.
źródło
B
ma skutki uboczne, tablica logiczna musi to uwzględnić.A && !B
sprawa nie była operacją:!(A && !B)
jest odpowiednikiem tego,!A || B
co oznacza, że możesz zrobićif (!A || B) { /* do action C */ }
i uniknąć pustego bloku.if (A && !B)
jest to naprawdę trudne do utrzymania dla przyszłych programistów, to naprawdę nie ma dla nich żadnej pomocy.Masz dwie możliwości:
Napisz funkcję, która wykonuje „akcję C”.
Zmień układ logiki tak, aby nie było tylu zagnieżdżonych instrukcji if. Zadaj sobie pytanie, jakie warunki powodują wystąpienie „działania C”. Wydaje mi się, że dzieje się tak, gdy „warunek B” jest prawdziwy lub „warunek A” jest fałszywy. Możemy to zapisać jako „NIE A LUB B”. Tłumacząc to na kod C, otrzymujemy
Aby dowiedzieć się więcej o tego rodzaju wyrażeniach, sugeruję wpisanie w wyszukiwarkę „algebry boolowskiej”, „logiki predykatów” i „rachunku predykatów”. To są głębokie zagadnienia matematyczne. Nie musisz uczyć się wszystkiego, tylko podstaw.
Warto również zapoznać się z „oceną zwarcia”. Z tego powodu kolejność wyrażeń jest ważna, aby dokładnie powielić oryginalną logikę. Chociaż
B || !A
jest logicznie równoważne, użycie tego jako warunku spowoduje wykonanie „akcji C”, gdyB
jest prawdziwe, niezależnie od wartościA
.źródło
...
jest . Jeśli to w ogóle nic (tj. „Wykonaj C, jeśli te warunki są spełnione; w przeciwnym razie nie rób nic”), to jest to oczywiście lepsze rozwiązanie, ponieważelse
można wtedy po prostu całkowicie pominąć stwierdzenie.Możesz uprościć to stwierdzenie w następujący sposób:
W przeciwnym razie umieść kod „C” w osobnej funkcji i wywołaj ją:
źródło
if (!A || B)
B || !A
spowoduje, żetrue
tylko wtedy , gdyB
jesttrue
, bez faktycznego sprawdzania zA
powodu zwarciaA
i coB
oznacza.W języku z dopasowywaniem wzorców możesz wyrazić rozwiązanie w sposób, który bardziej bezpośrednio odzwierciedla tabelę prawdy w odpowiedzi na pytanie.
Jeśli nie znasz składni, każdy wzorzec jest reprezentowany przez | po którym następują wartości do dopasowania z (a, b), a podkreślenie jest używane jako symbol wieloznaczny oznaczający „wszelkie inne wartości”. Ponieważ jedynym przypadkiem, w którym chcemy zrobić coś innego niż akcja c, jest sytuacja, w której a jest prawdą, a b jest fałszem, jawnie określamy te wartości jako pierwszy wzorzec (prawda, fałsz), a następnie robimy wszystko, co należy zrobić w takim przypadku. We wszystkich innych przypadkach przechodzimy do wzorca „wieloznacznego” i wykonujemy czynność c.
źródło
Opis problemu:
opisuje implikację : A implikuje B , logiczną propozycję równoważną
!A || B
(jak wspomniano w innych odpowiedziach):źródło
inline
dla C, aconstexpr
także dla C ++?Ugh, to też mnie zaskoczyło , ale jak wskazał Code-Apprentice, mamy gwarancję, że będziemy potrzebować
do action C
lub uruchomić zagnieżdżonyelse
blok, więc kod można uprościć do:Oto jak zajmujemy się trzema przypadkami:
do action C
w logice swojej pytanie jest wymaganacondition A
icondition B
będzietrue
- w tym logiki, jeśli osiągniemy 2 nd termin wif
-statement czym wiemy, żecondition A
jesttrue
w ten sposób wszystko, czego potrzebujemy, aby ocenić to, żecondition B
jesttrue
else
-blok w logice twojego pytania, który musiałcondition A
byćtrue
icondition B
byćfalse
- Jedynym sposobem, w jaki możemy dotrzeć doelse
-bloku w tej logice, byłoby gdybycondition A
byłytrue
icondition B
byłyfalse
else
blok w logice twojego pytania musicondition A
byćfalse
- W tej logice, jeślicondition A
jest fałszywa, my równieżdo action C
Podziękowania dla Code-Apprentice za wyprostowanie mnie tutaj. Proponuję przyjąć jego odpowiedź , ponieważ przedstawił ją poprawnie bez edycji: /
źródło
B
zostanie oszacowany tylko wtedy, gdy!A
jest fałszywy. Więc oba muszą zawieść, aby wykonaćelse
instrukcje.!A || B
jest fałszywa dokładnie wtedy, gdy oba!A
iB
są fałszywe. DlategoA
będzie prawdą, gdyelse
wykonuje. Nie ma potrzeby ponownej ocenyA
.W koncepcji logiki możesz rozwiązać ten problem w następujący sposób:
Jako udowodniony problem powoduje to
f = !a + b
. Istnieje kilka sposobów udowodnienia problemu, takich jak tabela prawdy, mapa Karnaugha i tak dalej.Tak więc w językach opartych na C możesz używać w następujący sposób:
PS: Mapa Karnaugh jest również używana w przypadku bardziej skomplikowanych serii warunków. Jest to metoda upraszczania wyrażeń algebry Boole'a.
źródło
Chociaż są już dobre odpowiedzi, pomyślałem, że to podejście może być jeszcze bardziej intuicyjne dla kogoś, kto jest nowy w algebrze Boole'a, niż ocena tabeli prawdy.
Pierwszą rzeczą, którą chcesz zrobić, jest sprawdzenie, w jakich warunkach chcesz wykonać C. Tak jest w przypadku, gdy
(a & b)
. Również kiedy!a
. Więc masz(a & b) | !a
.Jeśli chcesz zminimalizować, możesz kontynuować. Tak jak w „normalnej” arytmetyce, możesz pomnożyć.
(a & b) | !a = (a | !a) & (b | !a)
. a | ! a jest zawsze prawdziwe, więc możesz je po prostu przekreślić, co pozostawi zminimalizowany wynik:b | !a
. W przypadku, gdy kolejność ma znaczenie, ponieważ chcesz sprawdzić b tylko wtedy, gdy! A jest prawdziwe (na przykład, gdy! A jest sprawdzeniem zerowym, a b jest operacją na wskaźniku, jak @LordFarquaad wskazany w swoim komentarzu), możesz chcę zamienić te dwa.Drugi przypadek (/ * ... * /) będzie zawsze wykonywany, gdy c nie zostanie wykonane, więc możemy po prostu umieścić go w innym przypadku.
Warto również wspomnieć, że prawdopodobnie ma sens umieszczenie akcji c w metodzie.
Co pozostawia nam następujący kod:
W ten sposób możesz również zminimalizować terminy z większą liczbą operandów, co szybko staje się brzydkie w przypadku tablic prawdy. Innym dobrym podejściem są mapy Karnaugh. Ale nie będę teraz zagłębiał się w to.
źródło
Aby kod wyglądał bardziej jak tekst, użyj flag logicznych. Jeśli logika jest szczególnie niejasna, dodaj komentarze.
źródło
źródło
Wyodrębniłbym C do metody, a następnie zamknąłbym tę funkcję tak szybko, jak to możliwe we wszystkich przypadkach.
else
klauzule z jedną rzeczą na końcu powinny być prawie zawsze w miarę możliwości odwrócone. Oto przykład krok po kroku:Wyciąg C:
Odwróć najpierw,
if
aby pozbyć się pierwszegoelse
:Pozbądź się drugiego
else
:A potem możesz zauważyć, że te dwie sprawy mają to samo ciało i można je łączyć:
Opcjonalne rzeczy do poprawy to:
zależy od kontekstu, ale jeśli
!A || B
jest mylący, wyodrębnij go do jednej lub kilku zmiennych, aby wyjaśnić celw zależności od
C()
czyD()
to nie przypadek wyjątkowy powinien przejść ostatni, więc jeśliD()
jest wyjątek, a następnie odwrócićif
raz ostatniźródło
Używanie flag może również rozwiązać ten problem
źródło