Sorum şu:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
C eylem kodunu iki kez yerine bir kez yazmak mümkün müdür?
Nasıl basitleştirilir?
Sorum şu:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
C eylem kodunu iki kez yerine bir kez yazmak mümkün müdür?
Nasıl basitleştirilir?
Yanıtlar:
Bu tür problemlerde ilk adımınız her zaman bir mantık tablosu yapmaktır.
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
Masayı oluşturduktan sonra çözüm açıktır.
if (A && !B) {
...
}
else {
do action C
}
Bu mantığın daha kısa olsa da gelecekteki programcıların bakımı zor olabileceğini unutmayın.
B
yan etkileri varsa mantık tablosu bunu hesaba katmalıdır.
A && !B
durumun olmaması durumunda: buna !(A && !B)
eşdeğerdir, !A || B
bu da if (!A || B) { /* do action C */ }
boş bir blok yapabileceğiniz ve kaçınabileceğiniz anlamına gelir .
if (A && !B)
gelecek programcılar korumak için gerçekten zor, o zaman gerçekten hiç onlara yardımcı yoktur.
İki seçeneğiniz var:
"C eylemini" gerçekleştiren bir fonksiyon yazın.
Mantığınızı, çok fazla iç içe if ifadesi olmayacak şekilde yeniden düzenleyin. Kendinize hangi koşulların "C eylemine" neden olduğunu sorun. Bana "B koşulu" ya da "A koşulu" yanlış olduğunda olduğu gibi geliyor. Bunu "A OR B DEĞİL" olarak yazabiliriz. Bunu C koduna çevirerek,
if (!A || B) {
action C
} else {
...
}
Bu tür ifadeler hakkında daha fazla bilgi edinmek için, "boole cebiri", "yüklem mantığı" ve "yüklem hesabı" nı aramanızı öneririm. Bunlar derin matematiksel konular. Her şeyi öğrenmenize gerek yok, sadece temel bilgiler.
Ayrıca "kısa devre değerlendirmesi" hakkında bilgi edinmelisiniz. Bu nedenle, orijinal mantığınızı tam olarak çoğaltmak için ifadelerin sırası önemlidir. B || !A
Mantıksal olarak eşdeğer olsa da, bunu koşul olarak kullanmak B
, değeri ne olursa olsun, doğru olduğunda "C eylemini" yürütür A
.
...
olduğunu . Hiç bir şey değilse (yani, “bu koşullar karşılanırsa C yapın; aksi takdirde hiçbir şey yapmayın”), o zaman bu açıkça üstün bir çözümdür, çünkü else
ifade tamamen dışarıda bırakılabilir.
İfadeyi şu şekilde basitleştirebilirsiniz:
if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments
{
do C
}
Aksi takdirde 'C' kodunu ayrı bir fonksiyona koyun ve arayın:
DoActionC()
{
....
// code for Action C
}
if (condition A)
{
if(condition B)
{
DoActionC(); // call the function
}
else
...
}
else
{
DoActionC(); // call the function
}
if (!A || B)
B || !A
, kısa devre nedeniyle gerçekten kontrol etmeden, true
ancak B
şu şekilde sonuçlanırtrue
A
A
ve neyin temsil edildiğine bağlı olarak büyük bir fark olabilir B
.
Kalıp eşleşmesi olan bir dilde, çözümü QuestionC'nin cevabındaki doğruluk tablosunu daha doğrudan yansıtacak şekilde ifade edebilirsiniz.
match (a,b) with
| (true,false) -> ...
| _ -> action c
Sözdizimine aşina değilseniz, her bir desen bir | ardından (a, b) ile eşleşecek değerler gelir ve alt çizgi "diğer değerler" anlamına gelmek için joker karakter olarak kullanılır. C eyleminden başka bir şey yapmak istediğimiz tek durum a'nın doğru ve b'nin yanlış olduğu durum olduğundan, bu değerleri açıkça ilk kalıp (doğru, yanlış) olarak belirtiriz ve sonra bu durumda yapılması gerekeni yaparız. Diğer tüm durumlarda, "joker karakter" desenine geçiyoruz ve eylem yapıyoruz c.
Sorun bildirimi:
A koşulu eşleşirse, C eylemini gerçekleştirmek için B koşulunun eşleştirilmesi gerekir.
tarif ima : bir ima B , bir mantık teklif eşdeğer !A || B
(diğer yanıtlar belirtildiği gibi) hazırlanmıştır:
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
inline
C ve constexpr
C ++ için işaretleyin ?
Ugh, bu da beni harekete geçirdi, ancak Code-Apprentice tarafından işaret edildiği gibi do action C
, iç içe else
bloğu kullanmamız ya da çalıştırmamız gerekiyor , böylece kod basitleştirilebilir:
if (not condition A or condition B) {
do action C
} else {
...
}
3 vakayı şu şekilde vuruyoruz:
do action C
sizin Sorunun mantık gerekli condition A
ve condition B
olması true
- bu mantık, biz 2 ulaşırsa nd terimini if
-Bildirim sonra bunu biliyoruz condition A
olduğu true
o zamanın değerlendirmek için gereken tüm böylelikle condition B
olduğunutrue
else
sizin Sorunun mantık -blok- gerekli condition A
olduğu true
ve condition B
olmaya false
- biz ulaşmasının tek yolu else
ise olacaktı bu mantık -Blok condition A
vardı true
ve condition B
vardıfalse
else
Sorunuzun mantığındaki dış bloğun condition A
olması gerekiyor false
- Bu mantıkta condition A
yanlışsa biz dedo action C
Beni buradan düzelttiği için Code-Apprentice'den aksesuarlar. Cevabını kabul etmenizi öneririm , çünkü düzenlemeden doğru bir şekilde sundu: /
B
sadece !A
yanlışsa değerlendirilecektir . Bu nedenle, else
ifadeleri yürütmek için her ikisi de başarısız olmalıdır .
!A || B
her ikisi de tam olarak yanlış !A
ve B
yanlıştır. Bu nedenle, yürütüldüğünde A
doğru olacaktır else
. Yeniden değerlendirmeye gerek yok A
.
Mantık kavramında, bu sorunu aşağıdaki gibi çözebilirsiniz:
f = ab +! a
f =?
Kanıtlanmış bir sorun olarak, bu sonuçlanır f = !a + b
. Sorunu doğruluk tablosu, Karnaugh Haritası ve benzeri gibi kanıtlamanın bazı yolları vardır .
Yani C tabanlı dillerde aşağıdaki gibi kullanabilirsiniz:
if(!a || b)
{
// Do action C
}
Not: Karnaugh Haritası aynı zamanda daha karmaşık koşullar için de kullanılır. Boole cebri ifadelerini basitleştirmenin bir yöntemidir.
Zaten iyi cevaplar olmasına rağmen, bu yaklaşımın Boolean cebirinde yeni olan birine, daha sonra bir doğruluk tablosunu değerlendirmek için daha sezgisel olabileceğini düşündüm.
Yapmak istediğiniz ilk şey, hangi koşullar altında C yürütmek istediğinize bakmaktır (a & b)
. Ayrıca ne zaman !a
. Yani var (a & b) | !a
.
Eğer simge durumuna küçültmek isterseniz devam edebilirsiniz. Tıpkı "normal" aritmetiklerde olduğu gibi, çarpabilirsiniz.
(a & b) | !a = (a | !a) & (b | !a)
. a | ! Bir her zaman doğru, yani sadece minimize sonuçla hangi yaprakları, bunu geçebilir: b | !a
. Siparişin bir fark yaratması durumunda, sadece b! ikisini değiştirmek istiyorum.
Diğer durum (/ * ... * /), c yürütülmediğinde her zaman yürütülür, böylece başka bir duruma koyabiliriz.
Ayrıca, c eylemini bir yönteme koymanın her iki şekilde de mantıklı olduğu söylenebilir.
Bizi aşağıdaki kodla bırakır:
if (!A || B)
{
doActionC() // execute method which does action C
}
else
{
/* ... */ // what ever happens here, you might want to put it into a method, too.
}
Bu şekilde, doğruluk tablolarıyla hızla çirkin hale gelen daha fazla işlenenle terimleri en aza indirebilirsiniz. Bir başka iyi yaklaşım da Karnaugh haritaları. Ama şimdi bunun içine girmeyeceğim.
Kodun metne daha fazla benzemesini sağlamak için boole bayraklarını kullanın. Mantık özellikle belirsizse, yorum ekleyin.
bool do_action_C;
// Determine whether we need to do action C or just do the "..." action
// If condition A is matched, condition B needs to be matched in order to do action C
if (/* condition A */)
{
if(/* condition B */)
do_action_C = true; // have to do action C because blah
else
do_action_C = false; // no need to do action C because blarg
}
else
{
do_action_C = true; // A is false, so obviously have to do action C
}
if (do_action_C)
{
DoActionC(); // call the function
}
else
{
...
}
Bir yönteme C ayıklamak ve daha sonra her durumda işlevden en kısa sürede çıkmak. else
sonunda tek bir şey içeren maddeler mümkünse neredeyse her zaman ters çevrilmelidir. İşte adım adım örnek:
Özü C:
if (A) {
if (B)
C();
else
D();
} else
C();
İlk önce if
kurtulmak için önce ters çevir else
:
if (!A) {
C();
return;
}
if (B)
C();
else
D();
İkinciden kurtulun else
:
if (!A) {
C();
return;
}
if (B) {
C();
return;
}
D();
Ve sonra iki vakanın aynı gövdeye sahip olduğunu ve birleştirilebileceğini fark edebilirsiniz:
if (!A || B) {
C();
return;
}
D();
Geliştirilmesi gereken isteğe bağlı şeyler:
bağlama bağlıdır, ancak !A || B
kafa karıştırıcıysa amacı açıklamak için bir veya daha fazla değişkene çıkarın
hangisi C()
veya D()
olmayan istisnai durum eğer öyleyse, son gitmeli olan D()
istisna sonra invert olduğu if
son bir kez