Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带标志的数组_C++_Algorithm - Fatal编程技术网

C++ 带标志的数组

C++ 带标志的数组,c++,algorithm,C++,Algorithm,假设我有一个bool标志数组,它将根据条件设置为true或false 假设已经设置了索引1、2、6,并且没有设置所有其他标志,我需要调用function,如果已经设置了索引2、3、5,并且没有设置所有其他标志,我需要调用functionB。除此之外,是否有一种简单的方法可以执行上述逻辑: if(array[1] == true && array[2] == true && array[6] == true && array[3] == fa

假设我有一个bool标志数组,它将根据条件设置为true或false

假设已经设置了索引1、2、6,并且没有设置所有其他标志,我需要调用
function
,如果已经设置了索引2、3、5,并且没有设置所有其他标志,我需要调用
functionB
。除此之外,是否有一种简单的方法可以执行上述逻辑:

if(array[1] == true && array[2] == true && array[6] == true && 
   array[3] == false && array[4] == false && array[5] == false)
{
  functionA();
}
建议:

bool truecondition = array[1] && array[2] && array[6];
bool falsecondition = !array[3] && !array[4] && !array[5];

if (truecondition && falsecondition)
{
//do something
}

您可以跳过不必要的
==true
比较并使用
对于
false
情况:

if (array[1] && array[2] && array[6] && !array[3] && !array[4] && !array[5])
或者,制作布尔数组并与之进行比较:

bool condition[6] = { true, true, false, false, false, true };
if (std::equal(array+1, array+7, condition)) { // +1 for your 1-based indexes

更简单的方法是对所有这些标志使用整数,然后使用位操作。您还可以使用
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();

如果阵列具有固定大小,并且使用简单掩码进行测试,则可以使用
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();
}
#包括
void funcA(){
}
void funcB(){
}
枚举函数掩码{
funcA_Mask=0x23,//0010 0011
funcB_Mask=0x16,//0001 0110
};
int main(){
std::位集标志;
if(flags.to_ulong()&funcA_Mask)
funcA();
else if(flags.to_ulong()&funcB_Mask)
funcB();
}

您可以使用
char
代替
bool
,并将每个位视为一个标志。假设这个char标志(实际上是许多标志的组合)是这样的:

因此,如果设置了索引
1,2,6
,这意味着

//index count starts from rightmost bit
flags = 0100 0110 (binary) =  64 + 4 + 2 = 70 (decimal)
同样,索引
2,3,5
set意味着

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\u位
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)
enum标志
{
flag0=1维护和可读性噩梦!
请考虑以下情况:

bool temperature_sensor_tripped(const bool_array& flags)
{
     return flags[1];
}

// [...]

if (temperature_sensor_tripped(array) 
    && moisture_sensor_tripped(array)
    && !alarm_dispatched(array))
{
    functionA();
}

这样做的好处是,可以从其他函数调用
湿度传感器\u tripped()
及其亲属,而无需您(或维护人员)记住标记的顺序。

下面是使用
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;
}
#包括
#包括
布尔全部(常数标准::valarray和va){
返回va.min();
}
布尔无(常数标准::valarray和va){
return!va.max();
}
int main(){
布尔位_init[]={0,1,1,0,0,0,1};
std::valarray位(bits_init,7);
大小\u t真\u位\u init[]={1,2,6};
std::valarray真位(真位初始值,3);
大小\u t假\u位\u init[]={0,3,4,5};
std::VALARY false_位(false_位_init,4);
if(所有(位[真位])和&无(位[假位])

std::cout如果函数具有可在布尔上下文中计算的返回类型(例如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)。其他方面可以参考,这对于真正重复的代码是一个好主意

如果函数缺少这样的返回类型,可以使用带有返回类型的包装器来调用它们

或者,您可以使用提供索引访问的
操作符[]
将其作为对象,而不是普通数组,然后向其添加功能,以允许:

array.run_if(1, 2, 6, functionA)
     .run_if(2, 3, 5, functionB);
这里的主要问题是如何处理不同数量的索引。选项包括:

  • 1、2、3、4等指数的过载,假设上限可管理
  • 使用预处理器工具自动生成一组大但有限的重载(参见Loki或boost示例)
  • 首先使用函数,然后使用
    stdargs
    ,其前哨值为-1(无任意限制,但更容易出错)
  • 在代码< STD::vector < /COD>数组中接受索引(数组可以绑定到,发现元素的数目),尽管C++缺少“数组文字”,因此需要一个命名变量传递而不是<代码> RuniIF([ 1, 2, 6 ],函数A)< /C> >

如图所示,
run\u if
调用的链接建议
run\u if
返回对
*此
的引用,但这意味着在第一次匹配后继续匹配和潜在的函数调用。某些对象状态需要跟踪和阻止此操作。

您可以跳过
==true
部分,并替换
==false
运算符分离!
此数组是否有固定大小?@n.m.“you may”实际上应该是“you绝对应该”。我建议您将目标放在更易于阅读和理解的代码上,而不是那些花哨、乏味的东西。最好的源代码不是那些紧凑的代码,而是那些易于阅读和理解的代码。
&
您的标志将清除它们。您可能打算使用
+1源代码的一个关键方面是它您的解决方案最符合所有其他解决方案的标准。可以是
bool falsecondition=!truecondition
:P+1,但我会避免标识符中的否定词(如
false
),“
如果(!notDisabled())
”这会让我的大脑疼痛。我还会命名索引,例如
const int temperature\u sensor\u idx=1;
然后
return flags[temperature\u sensor\u idx]
@UncleZeiv:使用enum会更好…无论哪种方式,这样做都能获得Johnsyweb建议的包装函数的所有好处(以及更多)没有那么多的赘言。@Tony:是的,enum是一个不错的选择;无论如何,我建议除了Johnsyweb的解决方案之外,不要作为替代方案!@Unclzeiv:是的,我认为你是-这就是为什么我试图指出它实际上是一个有效的替代方案。。。。
array.run_if(1, 2, 6, functionA)
     .run_if(2, 3, 5, functionB);