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.
Byan etkileri varsa mantık tablosu bunu hesaba katmalıdır.
A && !Bdurumun olmaması durumunda: buna !(A && !B)eşdeğerdir, !A || Bbu 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 || !AMantı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ü elseifade 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, trueancak Bşu şekilde sonuçlanırtrueA
Ave 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 */
}
inlineC ve constexprC ++ 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 elsebloğ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 Csizin Sorunun mantık gerekli condition Ave condition Bolması true- bu mantık, biz 2 ulaşırsa nd terimini if-Bildirim sonra bunu biliyoruz condition Aolduğu trueo zamanın değerlendirmek için gereken tüm böylelikle condition Bolduğunutrueelsesizin Sorunun mantık -blok- gerekli condition Aolduğu trueve condition Bolmaya false- biz ulaşmasının tek yolu elseise olacaktı bu mantık -Blok condition Avardı trueve condition BvardıfalseelseSorunuzun mantığındaki dış bloğun condition Aolması gerekiyor false- Bu mantıkta condition Ayanlışsa biz dedo action CBeni buradan düzelttiği için Code-Apprentice'den aksesuarlar. Cevabını kabul etmenizi öneririm , çünkü düzenlemeden doğru bir şekilde sundu: /
Bsadece !Ayanlışsa değerlendirilecektir . Bu nedenle, elseifadeleri yürütmek için her ikisi de başarısız olmalıdır .
!A || Bher ikisi de tam olarak yanlış !Ave Byanlıştır. Bu nedenle, yürütüldüğünde Adoğ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. elsesonunda 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 ifkurtulmak 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 || Bkafa 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 ifson bir kez