降低C ++中的圈复杂度

时间:2020-10-29 14:58:25

标签: c++

我想问一个简单的if else语句,它具有多个条件 可以降低圈复杂度吗? 出于目的:

   std::string x; 
   if(cond)
     x = "Value1";
   else if(cond2)
   {
    if(cond3)
       x = "Value2";
    else if(cond4)
       x = "Value3";
    else
       x = "Value4";  
   }
   else if(cond5)
     x = "Value6";
   else if(cond6)
     x = "Value7";
       
   


   

4 个答案:

答案 0 :(得分:2)

我不得不用Google搜索它。 Wikipedia说:

循环复杂度是用于指示程序复杂度的软件度量。它是对程序源代码中线性独立路径数量的定量度量。

您可以绘制表格或图形:

                            *
                            |
                   ----------------------
                  |      |      |       |
                cond   cond2  cond5   cond6
                  |      |      |       |
                x+=1     |    x+=5    x+=6
                         |
                 -----------------
                 |       |       |
               cond3   cond4   else
                 |       |       |
               x+=2    x+=3    x+=4

现在您可以看到没有两个分支会导致相同的结果。如果我们找到导致相同结果的分支,那么我们可以尝试减少路径数量。同样,在没有更多信息的情况下,我必须假设所有条件都是独立的。如果它们之间存在关系,例如cond2 => cond3,则可以减少分支的数量。

答案 1 :(得分:0)

#include<stdio.h>

int main(){ 
    bool cond,cond1,cond2,cond3,cond4,cond5,cond6;
    
    cond6=true;
    int x=10;
    x+=cond?1:(cond2?(cond3?2:(cond4?3:4)):(cond5?5:(cond6?6:0)));
    
    printf("%d",x);
}

答案 2 :(得分:0)

您可以使用unsigned int中的位声明属性,并将这些属性组合以定义掩码。 background-position-x: center; background-position-y: center; 函数使用dispatch值和x值来测试这些位并做出相应的响应。

flag

样品运行:

#include <cstdint>
#include <iostream>

// Properties
static constexpr const auto C1 = 1u << 0;
static constexpr const auto C2 = 1u << 1;
static constexpr const auto C3 = 1u << 2;
static constexpr const auto C4 = 1u << 3;
static constexpr const auto C5 = 1u << 4;
static constexpr const auto C6 = 1u << 5;

// Masks (combination of properties)
static constexpr const auto C2C3 = C2 | C3;
static constexpr const auto C2C4 = C2 | C4;

// Dispatch operation based on flag (will jump, not branch)
int dispatch(int x, std::uint32_t flags) {
  switch (flags) {
    case C1:
      return x + 1;
    case C2:
      return x + 4;
    case C2C3:
      return x + 2;
    case C2C4:
      return x + 3;
    case C5:
      return x + 5;
    case C6:
      return x + 6;
    // add more cases as needed...

    default:
      // anything not specified is considered an error
      throw std::runtime_error("invalid flags");
  }
}

#define ASSERT(pred)                       \
  do {                                     \
    if (!(pred)) {                         \
      std::cerr << "expected " #pred "\n"; \
    } else {                               \
      std::cout << "ok " #pred "\n";       \
    }                                      \
  } while (false)

#define EXPECT_THROW(pred)                                \
  do {                                                    \
    bool thrown = false;                                  \
    try {                                                 \
      std::cout << (pred) << "\n";                        \
    } catch (...) {                                       \
      thrown = true;                                      \
    }                                                     \
    if (thrown) {                                         \
      std::cout << "ok " #pred "\n";                      \
    } else {                                              \
      std::cerr << "exception not thrown in " #pred "\n"; \
    }                                                     \
  } while (false)

int main() {
  // Only these should succeed
  ASSERT(dispatch(0, C1) == 1);
  ASSERT(dispatch(0, C2) == 4);
  ASSERT(dispatch(0, C2C3) == 2);
  ASSERT(dispatch(0, C2C4) == 3);
  ASSERT(dispatch(0, C5) == 5);
  ASSERT(dispatch(0, C6) == 6);

  // Anything else should be a failure (there are 2^6 = 64 combinations and only
  // 6 should succeed)... only a few are presented
  EXPECT_THROW(dispatch(0, C1 | C2));
  EXPECT_THROW(dispatch(0, C1 | C3));
  EXPECT_THROW(dispatch(0, C3 | C4));
  EXPECT_THROW(dispatch(0, C3));
}

可以轻松修改分派功能以添加更多案例。如果属性/标志具有更有意义的名称,那将更加有益。

答案 3 :(得分:-1)

说这整个复杂的代码块在FunctionMain()中,您可以将此代码移到另一个函数中,然后调用该函数。这样,复杂性就转移到了较低级别的功能上,并且可以读取主要代码。

另一种方法是将这段代码中的段拆分为可读的函数。