提问人:starf15h 提问时间:7/20/2017 最后编辑:Siyavash Hamdistarf15h 更新时间:10/26/2021 访问量:14335
如果条件 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
}
评论
if (!A || B)
B || !A
true
B
true
A
A
B
您有两种选择:
编写一个执行“操作 C”的函数。
重新排列逻辑,使没有那么多嵌套的 if 语句。问问自己,什么条件导致“动作C”发生。在我看来,当“条件 B”为真或“条件 A”为假时,就会发生这种情况。我们可以将其写为“NOT A OR B”。将其转换为 C 代码,我们得到
if (!A || B) { action C } else { ... }
要了解更多关于这类表达式的信息,我建议在谷歌上搜索“布尔代数”、“谓词逻辑”和“谓词演算”。这些都是深奥的数学主题。你不需要学习所有的东西,只需要学习基础知识。
您还应该了解“短路评估”。因此,表达式的顺序对于完全复制原始逻辑非常重要。虽然在逻辑上是等价的,但使用此作为条件将在 true 时执行“操作 C”,而不管 的值如何。B || !A
B
A
评论
,
可能会有实际的差异。如果它什么都不是(即,“如果满足这些条件,则执行 C;否则什么都不做“),那么这显然是更好的解决方案,因为该语句可以完全省略。else
呃,这也绊倒了我,但正如 Code-Apprentice 所指出的,我们保证需要或运行嵌套块,因此代码可以简化为:do action C
else
if (not condition A or condition B) {
do action C
} else {
...
}
这就是我们处理 3 种情况的方式:
- 嵌套在问题逻辑中 required 和 to be -- 在这个逻辑中,如果我们到达 -statement 中的第二个项,那么我们知道 因此我们需要评估的只是
do action C
condition A
condition B
true
if
condition A
true
condition B
true
- 问题逻辑中嵌套的 -block 需要 be 和 to be -- 在这个逻辑中,我们到达 -block 的唯一方法是 if were 和 were
else
condition A
true
condition B
false
else
condition A
true
condition B
false
- 你的问题逻辑中的外部块必须是 -- 在这个逻辑中,如果 is false,我们也
else
condition A
false
condition A
do action C
感谢 Code-Apprentice 在这里理顺了我。我建议接受他的答案,因为他在没有编辑的情况下正确地呈现了它:/
评论
B
!A
else
!A || B
!A
B
A
else
A
解决这类问题的第一步始终是制作一个逻辑表。
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 答案中的真值表的方式表达解决方案。
match (a,b) with
| (true,false) -> ...
| _ -> action c
如果您不熟悉语法,则每个模式都由 |后跟与 (a,b) 匹配的值,下划线用作通配符表示“任何其他值”。由于我们想要执行操作 c 以外的唯一情况是 a 为 true 而 b 为 false,因此我们明确地将这些值声明为第一个模式 (true,false),然后执行在这种情况下应该执行的任何操作。在所有其他情况下,我们都会陷入“通配符”模式并执行操作 c。
问题陈述:
如果条件 A 匹配,则需要匹配条件 B 才能执行操作 C
描述隐含:A 隐含 B,一个逻辑命题等价于(如其他答案中提到的):!A || B
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
评论
inline
constexpr
尽管已经有很好的答案,但我认为这种方法对于刚接触布尔代数的人来说可能更直观,然后计算真值表。
你要做的第一件事是看,你想在什么条件下执行C。当 .此外,当 .
所以你有.(a & b)
!a
(a & b) | !a
如果你想最小化,你可以继续。就像在“正常”算术中一样,你可以乘出去。
(a & b) | !a = (a | !a) & (b | !a)
.
a | !a 始终为 true,因此您可以将其划掉,从而得到最小化的结果:。
如果顺序有所不同,因为您只想在 !a 为 true 时检查 b(例如,当 !a 是空指针检查,b 是指针上的操作时,就像@LordFarquaad在他的注释中指出的那样),您可能需要切换两者。b | !a
另一种情况 (/* ... */) 总是在 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 地图。但我现在不会更深入地讨论这个问题。
我会将 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
因此,在基于 C 的语言中,您可以按如下方式使用:
if(!a || b)
{
// Do action C
}
P.S.:Karnaugh Map 也用于更复杂的一系列条件。 这是一种简化布尔代数表达式的方法。
if((A && B ) || !A)
{
//do C
}
else if(!B)
{
//...
}
使用标志也可以解决这个问题
int flag = 1;
if ( condition A ) {
flag = 2;
if( condition B ) {
flag = 3;
}
}
if(flag != 2) {
do action C
}
下一个:翻转布尔值的最简单方法?
评论