내 질문은 :
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
행동 코드 C를 두 번이 아니라 한 번만 쓰는 것이 가능합니까?
그것을 단순화하는 방법?
내 질문은 :
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
행동 코드 C를 두 번이 아니라 한 번만 쓰는 것이 가능합니까?
그것을 단순화하는 방법?
답변:
이러한 종류의 문제에서 첫 번째 단계는 항상 논리 테이블을 만드는 것입니다.
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
일단 테이블을 만들면 해결책이 분명합니다.
if (A && !B) {
...
}
else {
do action C
}
이 논리는 더 짧지 만 미래 프로그래머가 유지하기 어려울 수 있습니다.
B
에 부작용이있는 경우 논리 테이블이이를 설명해야합니다.
A && !B
케이스는 어떤 조합입니다 : !(A && !B)
에 해당 !A || B
당신이 할 수있는 것을 의미 if (!A || B) { /* do action C */ }
하고, 빈 블록을 피하십시오.
if (A && !B)
미래의 프로그래머가 유지하기가 정말 어려운 경우 에는 도움이되지 않습니다.
두 가지 옵션이 있습니다.
"액션 C"를 수행하는 함수를 작성하십시오.
중첩 된 if 문이 너무 많지 않도록 논리를 다시 정렬하십시오. "액션 C"가 발생하는 조건을 스스로에게 물어보십시오. "조건 B"가 참이거나 "조건 A"가 거짓 일 때 발생하는 것처럼 보입니다. 이것을 "NOT A OR B"로 쓸 수 있습니다. 이것을 C 코드로 변환하면
if (!A || B) {
action C
} else {
...
}
이러한 종류의 표현에 대해 자세히 알아 보려면 인터넷 검색 "부울 대수", "조건 자 논리"및 "조건 자 미적분학"을 제안합니다. 이것들은 깊은 수학적 주제입니다. 모든 것을 배울 필요는 없으며 기본 사항 만 있습니다.
"단락 평가"에 대해서도 배워야합니다. 이 때문에 표현식의 순서는 원래 논리를 정확하게 복제하는 데 중요합니다. B || !A
논리적으로 동일 하지만 이 값을 조건으로 사용 B
하면 값에 관계없이 true 일 때 "action C"가 실행됩니다 A
.
...
입니다 . 전혀 아무것도 없다면 (즉,“이러한 조건이 충족되면 C를 수행하고, 그렇지 않으면 아무것도하지 마십시오”), else
진술은 단순히 완전히 생략 될 수 있기 때문에 이것은 분명히 우수한 솔루션 입니다.
다음과 같이 설명을 단순화 할 수 있습니다.
if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments
{
do C
}
그렇지 않으면 'C'에 대한 코드를 별도의 함수에 넣고 호출하십시오.
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
는 단락으로 인해 실제로 확인하지 않고 is 인 true
경우에만 발생합니다B
true
A
A
및 B
위해 서있다.
패턴 일치가있는 언어에서는 QuestionC의 답변에 진리표를 더 직접 반영하는 방식으로 솔루션을 표현할 수 있습니다.
match (a,b) with
| (true,false) -> ...
| _ -> action c
구문에 익숙하지 않은 경우 각 패턴은 | 뒤에 (a, b)와 일치하는 값이 오며 밑줄은 "다른 값"을 의미하는 와일드 카드로 사용됩니다. 액션 c 이외의 다른 작업을 수행하려는 유일한 경우는 a가 true이고 b가 false 인 경우에만 해당 값을 첫 번째 패턴 (true, false)으로 명시한 다음이 경우 수행해야 할 모든 작업을 수행합니다. 다른 모든 경우에는 "와일드 카드"패턴으로 넘어 가서 조치 c를 수행합니다.
문제 진술 :
조건 A가 일치하면 조치 C를 수행하기 위해 조건 B를 일치시켜야합니다.
시사점 설명 : A 는 (다른 답변에서 언급했듯이) 논리적 제안 인 B를 의미합니다 !A || B
.
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
inline
C로 표시하고 constexpr
C ++로 표시합니까?
Ugh, 이것도 저를 트립 시켰지만 Code-Apprentice 가 지적한 것처럼do action C
중첩 else
블록 이 필요 하거나 실행 해야 하므로 코드를 다음과 같이 단순화 할 수 있습니다.
if (not condition A or condition B) {
do action C
} else {
...
}
이것이 우리가 세 가지 경우를 타격하는 방법입니다.
do action C
질문의 논리가 필요 condition A
하고 condition B
로 true
-이 논리에서, 우리는이 도달 할 경우 차 에서 용어를 if
-statement 우리가 아는 condition A
것입니다 true
우리가 즉 평가하기 위해 필요한 모든 따라서 condition B
이다true
else
질문의 논리 - 블록이 필요 condition A
로 true
하고 condition B
할 false
- 우리가 도달 할 수있는 유일한 방법 else
경우 것이이 논리 - 블록을 condition A
했다 true
하고 condition B
있었다false
else
질문의 논리 - 블록이 필요 condition A
로 false
하는 경우이 논리에 - condition A
우리는 또한 거짓do action C
나를 바로 잡기위한 코드 견습생을위한 제안. 그가 편집하지 않고 올바르게 제시했기 때문에 그의 대답을 수락하는 것이 좋습니다 .
B
경우에만 평가됩니다 !A
. 따라서 else
명령문 을 실행하려면 둘 다 실패해야합니다 .
!A || B
정확히 모두 거짓 !A
과 B
거짓. 따라서 실행 A
하면 true else
입니다. 재평가 할 필요가 없습니다 A
.
논리 개념에서이 문제를 다음과 같이 해결할 수 있습니다.
f = ab +! a
f =?
입증 된 문제로 결과는 다음과 같습니다 f = !a + b
. 진리표, Karnaugh지도 와 같은 문제를 증명하는 몇 가지 방법이 있습니다. .
따라서 C 기반 언어에서는 다음과 같이 사용할 수 있습니다.
if(!a || b)
{
// Do action C
}
PS : Karnaugh Map 은보다 복잡한 일련의 조건에도 사용됩니다. 부울 대수 표현을 단순화하는 방법입니다.
이미 좋은 대답이 있지만,이 접근법은 부울 대수를 처음 접한 사람에게 진리표를 평가하는 데 훨씬 직관적이라고 생각했습니다.
가장 먼저 할 일은 C를 실행하려는 조건에서 찾는 것 (a & b)
입니다. 또한 때 !a
. 그래서 당신은 있습니다 (a & b) | !a
.
최소화하고 싶다면 계속 진행할 수 있습니다. "정상적인"산술과 마찬가지로 곱할 수 있습니다.
(a & b) | !a = (a | !a) & (b | !a)
. | ! a는 항상 사실이므로 그냥 건너 뛸 수 있으므로 결과가 최소화됩니다.b | !a
. 순서에 차이가있는 경우! a가 true 인 경우에만 b를 검사하려고하기 때문에 (예 :! a가 nullpointer 검사이고 b가 @LordFarquaad가 주석에서 지적한 것과 같은 포인터에 대한 조작 인 경우), 둘을 바꾸고 싶어요
다른 경우 (/ * ... * /)는 c가 실행되지 않을 때 항상 실행되므로 else 경우에만 넣을 수 있습니다.
언급 할 가치가있는 것은 액션 c를 메소드에 넣는 방법 중 어느 것이나 의미가 있다는 것입니다.
다음과 같은 코드가 남습니다.
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.
}
이 방법으로 더 많은 피연산자가 포함 된 항을 최소화 할 수 있으며, 이는 진리표를 사용하여 빠르게 추한 것입니다. 또 다른 좋은 방법은 Karnaugh지도입니다. 하지만 지금은 더 깊이 들어 가지 않을 것입니다.
코드를 텍스트처럼 보이게하려면 부울 플래그를 사용하십시오. 논리가 명확하지 않은 경우 주석을 추가하십시오.
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
{
...
}
메소드에 C를 추출한 다음 가능한 한 빨리 함수를 종료합니다. else
끝에 하나의 것을 가진 절은 가능하면 거의 항상 반전되어야합니다. 단계별 예제는 다음과 같습니다.
추출 C :
if (A) {
if (B)
C();
else
D();
} else
C();
먼저 if
제거하려면 먼저 반전하십시오 else
.
if (!A) {
C();
return;
}
if (B)
C();
else
D();
두 번째를 제거하십시오 else
:
if (!A) {
C();
return;
}
if (B) {
C();
return;
}
D();
그리고 두 케이스가 동일한 몸체를 가지고 결합 될 수 있음을 알 수 있습니다.
if (!A || B) {
C();
return;
}
D();
개선해야 할 사항은 다음과 같습니다.
상황에 따라 다르지만 !A || B
혼동되는 경우 하나 이상의 변수로 추출하여 의도를 설명하십시오.
의 중 C()
또는 D()
비 예외적 인 경우 그렇게하는 경우는, 마지막으로 가야입니다 D()
예외가 다음 반전이며, if
마지막으로