如果条件 A 匹配,则需要匹配条件 B 才能执行操作 C
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 */
}
else
/* ... */
}
else
{
/* do action C */
}
是否可以将动作C的代码只写一次而不是两次?
如何简化呢?
你可以这样简化语句:
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
}
您有两个选择:
写一个函数执行"action C".
重新安排你的逻辑,这样你就没有那么多嵌套的 if 语句。问问自己什么条件导致 "action C" 发生。在我看来,它发生在 "condition B" 为真或 "condition A" 为假时。我们可以把它写成 "NOT A OR B"。将其翻译成 C 代码,我们得到
if (!A || B) {
action C
} else {
...
}
要了解有关此类表达式的更多信息,我建议使用谷歌搜索 "boolean algebra"、"predicate logic" 和 "predicate calculus"。这些是深奥的数学主题。您无需全部学习,只需学习基础知识即可。
您还应该了解 "short circuit evaluation"。因此,表达式的顺序对于准确复制原始逻辑很重要。虽然 B || !A
在逻辑上是等价的,但使用它作为条件将在 B
为真时执行 "action C" 而不管 A
.
的值如何
呃,这也把我绊倒了,但是由于 我们保证需要 do action C
或 运行 嵌套的-else
块,因此代码可以简化为:
if (not condition A or condition B) {
do action C
} else {
...
}
这就是我们处理 3 个案例的方式:
- 你问题逻辑中的嵌套
do action C
需要 condition A
和 condition B
为 true
-- 在这个逻辑中,如果我们达到 2nd term in the if
-statement 然后我们知道 condition A
是 true
因此我们需要评估的是 condition B
是 true
- 问题逻辑中嵌套的
else
块要求 condition A
为 true
并且 condition B
为 false
-- 唯一的方法如果 condition A
是 true
并且 condition B
是 false
,那么我们可以到达 else
-block
- 您问题逻辑中的外部
else
块要求 condition A
为 false
-- 在这个逻辑中,如果 condition A
为假,我们也 do action C
Code-Apprentice 在这里纠正我的方法。我建议接受 ,因为他没有编辑就正确地展示了它:/
解决此类问题的第一步始终是建立逻辑table。
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
完成 table 后,解决方案就很明确了。
if (A && !B) {
...
}
else {
do action C
}
请注意,此逻辑虽然较短,但未来的程序员可能难以维护。
在有模式匹配的语言中,你可以用更直接反映真相的方式表达解决方案-table问题C的答案
match (a,b) with
| (true,false) -> ...
| _ -> action c
如果您不熟悉语法,每个模式都由 | 表示后跟要与 (a,b) 匹配的值,下划线用作通配符,表示 "any other values"。由于我们想要做动作 c 以外的事情的唯一情况是当 a 为真且 b 为假时,我们明确地将这些值声明为第一个模式 (true,false),然后在这种情况下做任何应该做的事情。在所有其他情况下,我们进入 "wildcard" 模式并执行操作 c.
问题陈述:
If condition A is matched, condition B needs to be matched in order to do action C
描述implication:A蕴含B,逻辑命题等价至 !A || B
(如其他答案中所述):
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
尽管已经有很好的答案,但我认为这种方法对于刚接触布尔代数的人来说可能更直观,然后评估一个真值 table。
你首先要看,你要在什么条件下执行C。(a & b)
时就是这种情况。还有当!a
。
所以你有 (a & b) | !a
.
如果你想最小化你可以继续。就像在 "normal" 算术中一样,你可以相乘。
(a & b) | !a = (a | !a) & (b | !a)
。
一个 | !a 始终为真,因此您可以将其划掉,从而得到最小化的结果:b | !a
。
如果顺序有所不同,因为您只想在 !a 为真时检查 b(例如,当 !a 是空指针检查并且 b 是对指针的操作时,就像@LordFarquaad 在他的评论中指出的那样),您可能想交换两者。
另外一个case (/* ... */) 是c不执行的时候会一直执行,所以我们可以把它放在else case里。
另外值得一提的是,将操作 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.
}
通过这种方式,您还可以最小化具有更多操作数的项,这很快就会变得丑陋 tables。另一个好的方法是卡诺图。但我现在不会深入探讨这个问题。
我会将 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
最后一次
要使代码看起来更像文本,请使用布尔标志。如果逻辑特别晦涩,请添加评论。
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
{
...
}
在逻辑概念上,你可以这样解决这个问题:
f = a.b + !a
f = ?
作为一个已证明的问题,这导致 f = !a + b
。
证明问题的方法有table、Karnaugh Map等
因此,在基于 C 的语言中,您可以按如下方式使用:
if(!a || b)
{
// Do action C
}
P.S.: Karnaugh Map 也用于更复杂的一系列条件。
这是一种简化布尔代数表达式的方法。
if((A && B ) || !A)
{
//do C
}
else if(!B)
{
//...
}
使用flags也可以解决这个问题
int flag = 1;
if ( condition A ) {
flag = 2;
if( condition B ) {
flag = 3;
}
}
if(flag != 2) {
do action C
}
我的问题是:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
是否可以将动作C的代码只写一次而不是两次?
如何简化呢?
你可以这样简化语句:
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
}
您有两个选择:
写一个函数执行"action C".
重新安排你的逻辑,这样你就没有那么多嵌套的 if 语句。问问自己什么条件导致 "action C" 发生。在我看来,它发生在 "condition B" 为真或 "condition A" 为假时。我们可以把它写成 "NOT A OR B"。将其翻译成 C 代码,我们得到
if (!A || B) { action C } else { ... }
要了解有关此类表达式的更多信息,我建议使用谷歌搜索 "boolean algebra"、"predicate logic" 和 "predicate calculus"。这些是深奥的数学主题。您无需全部学习,只需学习基础知识即可。
您还应该了解 "short circuit evaluation"。因此,表达式的顺序对于准确复制原始逻辑很重要。虽然 B || !A
在逻辑上是等价的,但使用它作为条件将在 B
为真时执行 "action C" 而不管 A
.
呃,这也把我绊倒了,但是由于 do action C
或 运行 嵌套的-else
块,因此代码可以简化为:
if (not condition A or condition B) {
do action C
} else {
...
}
这就是我们处理 3 个案例的方式:
- 你问题逻辑中的嵌套
do action C
需要condition A
和condition B
为true
-- 在这个逻辑中,如果我们达到 2nd term in theif
-statement 然后我们知道condition A
是true
因此我们需要评估的是condition B
是true
- 问题逻辑中嵌套的
else
块要求condition A
为true
并且condition B
为false
-- 唯一的方法如果condition A
是true
并且condition B
是false
,那么我们可以到达 - 您问题逻辑中的外部
else
块要求condition A
为false
-- 在这个逻辑中,如果condition A
为假,我们也do action C
else
-block
Code-Apprentice 在这里纠正我的方法。我建议接受
解决此类问题的第一步始终是建立逻辑table。
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
完成 table 后,解决方案就很明确了。
if (A && !B) {
...
}
else {
do action C
}
请注意,此逻辑虽然较短,但未来的程序员可能难以维护。
在有模式匹配的语言中,你可以用更直接反映真相的方式表达解决方案-table问题C的答案
match (a,b) with
| (true,false) -> ...
| _ -> action c
如果您不熟悉语法,每个模式都由 | 表示后跟要与 (a,b) 匹配的值,下划线用作通配符,表示 "any other values"。由于我们想要做动作 c 以外的事情的唯一情况是当 a 为真且 b 为假时,我们明确地将这些值声明为第一个模式 (true,false),然后在这种情况下做任何应该做的事情。在所有其他情况下,我们进入 "wildcard" 模式并执行操作 c.
问题陈述:
If condition A is matched, condition B needs to be matched in order to do action C
描述implication:A蕴含B,逻辑命题等价至 !A || B
(如其他答案中所述):
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
尽管已经有很好的答案,但我认为这种方法对于刚接触布尔代数的人来说可能更直观,然后评估一个真值 table。
你首先要看,你要在什么条件下执行C。(a & b)
时就是这种情况。还有当!a
。
所以你有 (a & b) | !a
.
如果你想最小化你可以继续。就像在 "normal" 算术中一样,你可以相乘。
(a & b) | !a = (a | !a) & (b | !a)
。
一个 | !a 始终为真,因此您可以将其划掉,从而得到最小化的结果:b | !a
。
如果顺序有所不同,因为您只想在 !a 为真时检查 b(例如,当 !a 是空指针检查并且 b 是对指针的操作时,就像@LordFarquaad 在他的评论中指出的那样),您可能想交换两者。
另外一个case (/* ... */) 是c不执行的时候会一直执行,所以我们可以把它放在else case里。
另外值得一提的是,将操作 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.
}
通过这种方式,您还可以最小化具有更多操作数的项,这很快就会变得丑陋 tables。另一个好的方法是卡诺图。但我现在不会深入探讨这个问题。
我会将 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
最后一次
要使代码看起来更像文本,请使用布尔标志。如果逻辑特别晦涩,请添加评论。
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
{
...
}
在逻辑概念上,你可以这样解决这个问题:
f = a.b + !a
f = ?
作为一个已证明的问题,这导致 f = !a + b
。
证明问题的方法有table、Karnaugh Map等
因此,在基于 C 的语言中,您可以按如下方式使用:
if(!a || b)
{
// Do action C
}
P.S.: Karnaugh Map 也用于更复杂的一系列条件。 这是一种简化布尔代数表达式的方法。
if((A && B ) || !A)
{
//do C
}
else if(!B)
{
//...
}
使用flags也可以解决这个问题
int flag = 1;
if ( condition A ) {
flag = 2;
if( condition B ) {
flag = 3;
}
}
if(flag != 2) {
do action C
}