基于两个布尔变量的分支

发布于 2024-11-28 00:12:47 字数 1011 浏览 0 评论 0原文

假设我有两个布尔变量,并且我想根据它们的值做完全不同的事情。实现这一目标的最干净的方法是什么?

变体 1:

if (a && b)
{
    // ...
}
else if (a && !b)
{
    // ...
}
else if (!a && b)
{
    // ...
}
else
{
    // ...
}

变体 2:

if (a)
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}
else
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}

变体 3:

switch (a << 1 | b)
{
case 0:
    // ...
    break;

case 1:
    // ...
    break;

case 2:
    // ...
    break;

case 3:
    // ...
    break;
}

变体 4:

lut[a][b]();

void (*lut[2][2])() = {false_false, false_true, true_false, true_true};

void false_false()
{
    // ...
}

void false_true()
{
    // ...
}

void true_false()
{
    // ...
}

void true_true()
{
    // ...
}

变体 3 和 4 是否过于棘手/复杂普通程序员?我错过了任何其他变体吗?

Suppose I have two boolean variables, and I want to do completely different things based on their values. What is the cleanest way to achieve this?

Variant 1:

if (a && b)
{
    // ...
}
else if (a && !b)
{
    // ...
}
else if (!a && b)
{
    // ...
}
else
{
    // ...
}

Variant 2:

if (a)
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}
else
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}

Variant 3:

switch (a << 1 | b)
{
case 0:
    // ...
    break;

case 1:
    // ...
    break;

case 2:
    // ...
    break;

case 3:
    // ...
    break;
}

Variant 4:

lut[a][b]();

void (*lut[2][2])() = {false_false, false_true, true_false, true_true};

void false_false()
{
    // ...
}

void false_true()
{
    // ...
}

void true_false()
{
    // ...
}

void true_true()
{
    // ...
}

Are variants 3 and 4 too tricky/complicated for the average programmer? Any other variants I have missed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ぃ双果 2024-12-05 00:12:47

第一个变体是最清晰、最易读的,但可以调整:

if (a && b) {
    // ...
} else if (a) { // no need to test !b here - b==true would be the first case
    // ...
} else if (b) { //no need to test !a here - that would be the first case
    // ...
} else { // !a&&!b - the last remaining
    // ...
}

The first variant is the clearest and most readable, but it can be adjusted:

if (a && b) {
    // ...
} else if (a) { // no need to test !b here - b==true would be the first case
    // ...
} else if (b) { //no need to test !a here - that would be the first case
    // ...
} else { // !a&&!b - the last remaining
    // ...
}
游魂 2024-12-05 00:12:47

您忘记了:

if (a) a_true(b);
else a_false(b);

当适用且您确实需要 4 种不同的行为时,这可能是最佳选择。

如果你有超过 2 个布尔值,如果我有 2^n 种不同的行为,而这些行为不能像上面那样很好地分解,我会将其视为代码味道。然后我可能会考虑这样做:

enum { case1, case2, ... }

int dispatch_cases(bool a, bool b, bool c, ..., bool z);

switch (dispatch_cases(a, b, ..., z))
{
case case1:
    ...
};

但是没有上下文,很难判断这样的复杂性是否有必要。

You forgot about:

if (a) a_true(b);
else a_false(b);

which is probably the best choice when appliable, and when you truly need 4 different behaviours.

If you have more than 2 bools, I take this as a code smell if I have 2^n different behaviours which don't factorize well like the above. Then I may think about doing:

enum { case1, case2, ... }

int dispatch_cases(bool a, bool b, bool c, ..., bool z);

switch (dispatch_cases(a, b, ..., z))
{
case case1:
    ...
};

but without context, it is hard to tell whether such complexity is necessary.

撧情箌佬 2024-12-05 00:12:47

恕我直言,我会选择变体3。因为就我个人而言,当我检查相等性时,我不喜欢 if/else。它明确指出只有4种可能性。

一个小的修改是:

inline int STATES(int X, int Y) { return (X<<1) | Y; }
// ...
switch (STATES(a,b))

为了使其更奇特,您也可以将 0,1,2,3 替换为 enum

enum States {
  NONE,
  ONLY_B.
  ONLY_A,
  BOTH
}; 

IMHO, I will go for variant 3. Because personally, I don't like if/else when I am checking for equality. It clearly states that there are only 4 possibilities.

One minor edit would be:

inline int STATES(int X, int Y) { return (X<<1) | Y; }
// ...
switch (STATES(a,b))

To make it more fancy, you may replace 0,1,2,3 with an enum as well.

enum States {
  NONE,
  ONLY_B.
  ONLY_A,
  BOTH
}; 
白日梦 2024-12-05 00:12:47

对于只有两个布尔值的情况,其中任何一个都是好的且合理的。大家可以根据自己的口味来选择。

但是,如果有两个以上的布尔值,例如四个布尔值,那么我个人会使用查找表,并且我会这样做:

typedef void (*functype)();

//16 functions to handle 16 cases!
void f0() {}
void f1() {}
//...so on
void f15() {}

//setup lookup table
functype lut[] = 
{
    f0,   //0000 - means all bool are false
    f1,   //0001
    f2,   //0010
    f3,   //0011
    f4,   //0100
    f5,   //0101
    f6,   //0110
    f7,   //0111
    f8,   //1000
    f9,   //1001
    f10,  //1010
    f11,  //1011
    f12,  //1100
    f13,  //1101
    f14,  //1110
    f15   //1111 - means all bool are true
};

lut[MakeInt(b1,b2,b3,b4)](); //call

MakeInt() 很容易写:

int MakeInt(bool b1, bool b2, bool b3, bool b4)
{
   return b1 | (b2<<1) | (b3 <<2) | (b4<<3);
}

For just two booleans, any of them is good and reasonable. One can choose based on his taste.

However, if there are more than two booleans, say four booleans, then I personally would go with lookup table, and I would do this as:

typedef void (*functype)();

//16 functions to handle 16 cases!
void f0() {}
void f1() {}
//...so on
void f15() {}

//setup lookup table
functype lut[] = 
{
    f0,   //0000 - means all bool are false
    f1,   //0001
    f2,   //0010
    f3,   //0011
    f4,   //0100
    f5,   //0101
    f6,   //0110
    f7,   //0111
    f8,   //1000
    f9,   //1001
    f10,  //1010
    f11,  //1011
    f12,  //1100
    f13,  //1101
    f14,  //1110
    f15   //1111 - means all bool are true
};

lut[MakeInt(b1,b2,b3,b4)](); //call

MakeInt() is easy to write:

int MakeInt(bool b1, bool b2, bool b3, bool b4)
{
   return b1 | (b2<<1) | (b3 <<2) | (b4<<3);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文