Pertanyaanku adalah:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Apakah mungkin untuk hanya menulis kode tindakan C satu kali, bukan dua kali?
Bagaimana cara menyederhanakannya?
Jawaban:
Langkah pertama Anda dalam masalah seperti ini adalah selalu membuat tabel logika.
Setelah Anda membuat tabel, solusinya jelas.
Perhatikan bahwa logika ini, walaupun lebih pendek, mungkin sulit untuk diprogram oleh programmer di masa depan.
sumber
B
memiliki efek samping, tabel logika harus menjelaskannya.A && !B
ini adalah no-op:!(A && !B)
setara dengan!A || B
yang berarti Anda dapat melakukanif (!A || B) { /* do action C */ }
dan menghindari blok kosong.if (A && !B)
benar-benar sulit untuk dipelihara oleh programmer di masa depan, maka tidak ada yang bisa membantu mereka.Anda memiliki dua opsi:
Tulis fungsi yang melakukan "tindakan C".
Atur ulang logika Anda sehingga Anda tidak memiliki begitu banyak pernyataan bersarang jika. Tanyakan pada diri Anda kondisi apa yang menyebabkan "tindakan C" terjadi. Sepertinya saya terjadi ketika "kondisi B" benar atau "kondisi A" salah. Kita dapat menulis ini sebagai "BUKAN ATAU B". Menerjemahkan ini ke dalam kode C, kita dapatkan
Untuk mempelajari lebih lanjut tentang ekspresi semacam ini, saya sarankan googling "aljabar boolean", "logika predikat", dan "predikat kalkulus". Ini adalah topik matematika yang mendalam. Anda tidak perlu mempelajari semuanya, hanya dasar-dasarnya.
Anda juga harus belajar tentang "evaluasi hubung singkat". Karena itu, urutan ekspresi penting untuk menduplikasi logika asli Anda secara tepat. Meskipun
B || !A
secara logika setara, menggunakan ini sebagai kondisi akan mengeksekusi "aksi C" ketikaB
benar terlepas dari nilaiA
.sumber
...
adalah . Jika tidak ada sama sekali (yaitu, "lakukan C jika kondisi ini terpenuhi; jika tidak lakukan apa-apa"), maka ini jelas merupakan solusi yang unggul, karenaelse
pernyataan itu bisa ditinggalkan begitu saja.Anda dapat menyederhanakan pernyataan seperti ini:
Kalau tidak, letakkan kode untuk 'C' di fungsi terpisah dan panggil:
sumber
if (!A || B)
B || !A
akan menghasilkantrue
jikaB
adatrue
, tanpa benar-benar memeriksaA
karena korsletingA
danB
berdiri untuk.Dalam bahasa dengan pencocokan pola, Anda dapat mengekspresikan solusi dengan cara yang lebih langsung mencerminkan tabel kebenaran dalam jawaban QuestionC.
Jika Anda tidak terbiasa dengan sintaks, setiap pola diwakili oleh | diikuti oleh nilai yang cocok dengan (a, b), dan garis bawah digunakan sebagai wildcard yang berarti "nilai lain". Karena satu-satunya kasus di mana kita ingin melakukan sesuatu selain tindakan c adalah ketika a benar dan b salah, kita secara eksplisit menyatakan nilai-nilai itu sebagai pola pertama (benar, salah) dan kemudian melakukan apa pun yang harus dilakukan dalam kasus itu. Dalam semua kasus lain, kita masuk ke pola "wildcard" dan melakukan tindakan c.
sumber
Pernyataan masalah:
menggambarkan implikasi : A menyiratkan B , proposisi logis yang setara dengan
!A || B
(sebagaimana disebutkan dalam jawaban lain):sumber
inline
untuk C danconstexpr
juga untuk C ++?Ugh, ini juga membuat saya tersandung, tetapi seperti yang ditunjukkan oleh Code-Apprentice, kami dijamin perlu
do action C
atau menjalankanelse
blok bersarang , sehingga kode dapat disederhanakan untuk:Inilah cara kami menekan 3 kasus:
do action C
dalam logika pertanyaan Anda diperlukancondition A
dancondition B
menjaditrue
- Dalam logika ini, jika kita mencapai 2 nd istilah dalamif
pernyataan-maka kita tahu bahwacondition A
adalahtrue
sehingga semua kita perlu mengevaluasi adalah bahwacondition B
adalahtrue
else
Blok- dalam logika pertanyaan Anda haruscondition A
adatrue
dancondition B
menjadifalse
- Satu-satunya cara bahwa kita dapat mencapaielse
-block dalam logika ini akan jikacondition A
beradatrue
dancondition B
yangfalse
else
Blok- dalam logika pertanyaan Andacondition A
harusfalse
- Dalam logika ini, jikacondition A
itu salah, kami jugado action C
Alat Peraga untuk Magang-Kode untuk meluruskan saya di sini. Saya sarankan menerima jawabannya , karena ia menyajikannya dengan benar tanpa mengedit: /
sumber
B
akan dievaluasi hanya jika!A
salah. Jadi keduanya harus gagal untuk menjalankanelse
pernyataan.!A || B
adalah salah persis ketika keduanya!A
danB
itu salah. Karena itu,A
akan benar ketikaelse
dieksekusi. Tidak perlu mengevaluasi kembaliA
.Dalam konsep logika, Anda bisa menyelesaikan masalah ini sebagai berikut:
Sebagai masalah yang terbukti, ini menghasilkan
f = !a + b
. Ada beberapa cara untuk membuktikan masalah seperti tabel kebenaran, Karnaugh Map dan sebagainya.Jadi, dalam bahasa berbasis C Anda dapat menggunakan sebagai berikut:
PS: Karnaugh Map juga digunakan untuk serangkaian kondisi yang lebih rumit. Ini adalah metode penyederhanaan ekspresi aljabar Boolean.
sumber
Meskipun sudah ada jawaban yang bagus, saya berpikir bahwa pendekatan ini mungkin lebih intuitif bagi seseorang yang baru mengenal aljabar Boolean kemudian mengevaluasi tabel kebenaran.
Hal pertama yang ingin Anda lakukan adalah melihat, di bawah kondisi apa Anda ingin mengeksekusi C. Ini adalah kasus ketika
(a & b)
. Juga kapan!a
. Jadi kamu punya(a & b) | !a
.Jika Anda ingin meminimalkan, Anda dapat melanjutkan. Sama seperti dalam aritmatika "normal", Anda dapat mengalikan.
(a & b) | !a = (a | !a) & (b | !a)
. a | ! a selalu benar, jadi Anda bisa mencoretnya, yang membuat Anda dengan hasil minimal:b | !a
. Dalam hal urutan membuat perbedaan, karena Anda ingin memeriksa b hanya jika! A benar (misalnya ketika! A adalah cek nullpointer dan b adalah operasi pada pointer seperti @LordFarquaad ditunjukkan dalam komentarnya), Anda mungkin ingin mengganti keduanya.Kasus lain (/ * ... * /) akan selalu dieksekusi ketika c tidak dieksekusi, jadi kita bisa memasukkannya ke dalam kasus lain.
Yang juga layak disebutkan adalah bahwa mungkin masuk akal untuk memasukkan tindakan c ke dalam metode.
Yang membuat kita dengan kode berikut:
Dengan cara ini Anda juga dapat meminimalkan istilah dengan lebih banyak operan, yang dengan cepat menjadi jelek dengan tabel kebenaran. Pendekatan lain yang baik adalah peta Karnaugh. Tapi saya tidak akan membahas ini lebih dalam lagi.
sumber
Untuk membuat kode lebih mirip teks, gunakan bendera boolean. Jika logikanya tidak jelas, tambahkan komentar.
sumber
sumber
Saya akan mengekstrak C ke suatu metode, dan kemudian keluar dari fungsi sesegera mungkin dalam semua kasus.
else
klausa dengan satu hal di akhir harus hampir selalu dibalik jika memungkinkan. Inilah contoh langkah demi langkah:Ekstrak C:
Balikkan dulu
if
untuk menyingkirkan duluelse
:Singkirkan yang kedua
else
:Dan kemudian Anda dapat melihat bahwa kedua kasing memiliki badan yang sama dan dapat digabungkan:
Hal-hal opsional untuk ditingkatkan adalah:
tergantung pada konteks, tetapi jika
!A || B
membingungkan, ekstrak ke satu atau lebih variabel untuk menjelaskan maksudkasus mana pun
C()
atauD()
non-luar biasa harus menjadi yang terakhir, jadi jikaD()
pengecualian, maka membalikkan yangif
terakhir kalinyasumber
Menggunakan bendera juga dapat mengatasi masalah ini
sumber