假设我有一个bool标志数组,它将设置为true或false取决于条件。
假设索引1,2,6已经设置且所有其他标志都没有设置,我需要调用functionA
,如果索引2,3,5已经设置,所有其他标志都没有设置,我需要拨打functionB
。除了这样做之外,还有一种简单的方法可以执行上述逻辑:
if(array[1] == true && array[2] == true && array[6] == true &&
array[3] == false && array[4] == false && array[5] == false)
{
functionA();
}
答案 0 :(得分:8)
请考虑一下:
bool temperature_sensor_tripped(const bool_array& flags)
{
return flags[1];
}
// [...]
if (temperature_sensor_tripped(array)
&& moisture_sensor_tripped(array)
&& !alarm_dispatched(array))
{
functionA();
}
这样做的好处是moisture_sensor_tripped()
及其亲属可以在没有你(或维护者)记住标志顺序的情况下从其他函数调用。
答案 1 :(得分:5)
建议:
bool truecondition = array[1] && array[2] && array[6];
bool falsecondition = !array[3] && !array[4] && !array[5];
if (truecondition && falsecondition)
{
//do something
}
答案 2 :(得分:3)
您可以跳过不必要的== true
比较,并对!
案例使用false
:
if (array[1] && array[2] && array[6] && !array[3] && !array[4] && !array[5])
或者,制作一个bool数组并与之进行比较:
bool condition[6] = { true, true, false, false, false, true };
if (std::equal(array+1, array+7, condition)) { // +1 for your 1-based indexes
答案 3 :(得分:3)
而不是bool
,您可以使用char
代替,并将每个位视为一个标志。假设这个 char 标志(实际上是许多标志的组合)是这样的:
char flags;
因此,如果设置索引1,2,6
,则意味着
//index count starts from rightmost bit
flags = 0100 0110 (binary) = 64 + 4 + 2 = 70 (decimal)
同样,索引2,3,5
设置意味着
flags = 0010 1100 (binary) = 32 + 8 + 4 = 44 (decimal)
所以你可以写
if (flags == 70 ) //i.e when index 1,2,6 are set
{
functionA();
}
else if ( flags == 44 ) //i.e when index 2,3,5 are set
{
functionB();
}
由于char
的大小是一个字节,因此您的计算机上最多可以包含8
个标记(假设CHAR_BIT
是8
,这很可能是是真实的)。但是你需要更多的标志,然后你可以改为int
,并相应地工作。
嗯,这是基本的想法。现在您可以按如下方式改进:
enum flag
{
flag0 = 1 << 0, //1 = 0000 0001
flag1 = 1 << 1, //2 = 0000 0010
flag2 = 1 << 2, //4 = 0000 0100
flag3 = 1 << 3, //8 = 0000 1000
flag4 = 1 << 4, //16 = 0001 0000
flag5 = 1 << 5, //32 = 0010 0000
flag6 = 1 << 6, //64 = 0100 0000
flag7 = 1 << 7, //128 = 1000 0000
};
char flags = 0 ;
//this is how you can set flags!
flags |= flag1 ; //set index 1 (one at a time)
flags |= flag2 | flag6 ; //set index 2 and 6 (more than one at a time)
if ( flags == (flag1 | flag2 | flag6) )
{
functionA();
}
else if ( flags == (flag2 | flag3 | flag5) )
{
functionB();
}
//and this is how you can unset flags!
flags &= ~flag1 ; //unset index 1 (one at a time)
flags &= ~flag2 & ~flag6 ; //unset index 2 and 6 (more than one at a time)
请参阅此在线演示:http://www.ideone.com/6BdGf
答案 4 :(得分:2)
如果数组具有固定大小并使用简单掩码进行测试,则可以使用std::bitset
:
#include <bitset>
void funcA(){
}
void funcB(){
}
enum FuncMasks{
funcA_Mask = 0x23, // 0010 0011
funcB_Mask = 0x16, // 0001 0110
};
int main(){
std::bitset<6> flags;
if(flags.to_ulong() & funcA_Mask)
funcA();
else if(flags.to_ulong() & funcB_Mask)
funcB();
}
答案 5 :(得分:1)
更简单的方法是对所有这些标志使用整数,然后使用位操作。如果您正在寻找可以使用的解决方案,也可以使用std::bitset
。
enum flags { // i use hexadecimal notation as it's easier to see unused flags - using 8 bits/1 byte is enough for you but you could extend it even more as well
FLAG_NONE = 0x00;
FLAG_ONE = 0x01;
FLAG_TWO = 0x02;
FLAG_THREE = 0x04;
// ...
};
// To set some flags you use bitwise operators:
char flags_set = FLAG_ONE | FLAG_THREE | FLAG_SIX;
flags_set |= FLAG_FOUR; // add fourth flag
flags_set &= ~FLAG_TWO; // remove second flag (if set)
// Similar way you can check the flags and you've got "talking" code that's a lot easier to understand than tons of if()s
if (flags_set & (FLAG_ONE | FLAG_TWO | FLAG_SIX))
functionA();
elseif (flags_set & (FLAG_TWO | FLAG_THREE | FLAG_FIVE))
functionB();
答案 6 :(得分:0)
以下是使用valarray
的替代方法:
#include <valarray>
#include <iostream>
bool all(const std::valarray<bool> & va) {
return va.min();
}
bool none(const std::valarray<bool> & va) {
return !va.max();
}
int main() {
bool bits_init[] = {0, 1, 1, 0, 0, 0, 1};
std::valarray<bool> bits(bits_init, 7);
size_t true_bits_init[] = {1, 2, 6};
std::valarray<size_t> true_bits(true_bits_init, 3);
size_t false_bits_init[] = {0, 3, 4, 5};
std::valarray<size_t> false_bits(false_bits_init, 4);
if(all(bits[true_bits]) && none(bits[false_bits]))
std::cout << "functionA" << std::endl;
else
std::cout << "functionB" << std::endl;
bits[2] = false;
if(all(bits[true_bits]) && none(bits[false_bits]))
std::cout << "functionA" << std::endl;
else
std::cout << "functionB" << std::endl;
bits[2] = true;
bits[3] = true;
if(all(bits[true_bits]) && none(bits[false_bits]))
std::cout << "functionA" << std::endl;
else
std::cout << "functionB" << std::endl;
}
我不知道你是否需要它。如果阵列的大小不同,它确实提供了很大的灵活性。
答案 7 :(得分:0)
如果函数有一个可以在布尔上下文中计算的返回类型(例如bool,int,double,pointer),你可以写:
Array& a = array; // for brevity...
a[1] && a[2] && a[6] && functionA() ||
a[2] && a[3] && a[5] && functionB() ||
...
您可能会或可能不会将此&&
函数链接到明确的“if”用法(上面的风格受到一些perl黑客,FWIW的欢迎)。参考的其他方面,这是真正重复的代码的好主意。
如果函数缺少这样的返回类型,则可以使用带有返回类型的包装器来调用它们。
或者,您可以使用operator[]
提供索引访问权限,而不是使用普通数组,然后向其添加功能,允许:
array.run_if(1, 2, 6, functionA)
.run_if(2, 3, 5, functionB);
这里,主要问题是如何处理不同数量的指数。选项包括:
...
和stdargs
,使用-1(没有任意限制,但更容易出错)的标记值std::vector<>
数组中的索引(模板可以绑定,发现元素数量,但C ++缺少“数组文字”,所以你需要一个命名变量而不是{{1} }。如图所示,run_if([1, 2, 6], functionA)
调用的链接建议run_if
返回对run_if
的引用,但这意味着在第一次匹配后继续匹配和潜在的函数调用。某些对象状态需要跟踪并阻止这种情况。