1

I'm looking for a control structure to deal with potentially multiple blocks of code or a NONE block. The most basic case is when there are only two conditions, A and B:

+-------+-------+------------+
|   A   |   B   | Blocks Run |
+-------+-------+------------+
| false | false | C          |
| false | true  | B          |
| true  | false | A          |
| true  | true  | A + B      |
+-------+-------+------------+

The best thing I have so far is:

if( A )
{
    // Run Block A
}

if( B )
{
    //Run Block B
}
else if( !A )
{
    //Run Block C
}
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

4 Answers4

4

If it's all about minimising comparsions using a table is the only way to go.

switch ((B << 1) | A)
{
  case 0:
    // C
    break;

  case 0b01: // case 1:
    // A
    break;

  case 0b10: // case 2:
    // B
    break;

  case 0b11: // case 3:
    // A
    // B
    break;

  default:
    // Shouldn't arrive here.
    break;
}
alk
  • 69,737
  • 10
  • 105
  • 255
  • 2
    Nice solution, an additional suggestion: make `case 0b11` fall through to `case 0b01` so you don't have to write block `B` twice. – DarkDust Feb 07 '14 at 12:41
  • I had considered this as well... It suffers from code replication similarly to @Dark Dust's answer. And would become unwieldy for a higher number of conditionals. – Jonathan Mee Feb 07 '14 at 12:41
  • @JonathanMee: Shifting the blocks (A, B, C) to functions, I wouldn't consider this messy. – alk Feb 07 '14 at 12:44
  • @DarkDust: The fall through doesn't make this more readable. I'd leave the optimisation to the compiler. – alk Feb 07 '14 at 12:45
3

For clarity, I'm going to rename your conditions P and Q (as is the convention in propositional logic)

if( P || Q)
{
    P && A();
    Q && B();
}
else
{
    C();
}

Edit:

adding more checks is rather easy:

if( P || Q || R || S)
{
    P && A();
    Q && B();
    R && D();
    S && E();
}
else
{
    C();
}

Edit, after comment:

Well how about this.

int runC = 1;
P && (runC=0, A());
Q && (runC=0, B());
R && (runC=0, D());
S && (runC=0, E());
runC && C();
Andrejovich
  • 544
  • 2
  • 13
1

If you just want to evaluate each condition once:

if (a) {
  A();
  if (b) {
    B();
  }
} else if (b) {
  B();
} else {
  C()
}

I don't think it's much better than your code, though. While it does evaluate the condition only once, the code blocks to execute are now duplicated. As far as I can see, you'll either have to evaluate a condition twice or a write a code block twice. In that case, I'd prefer evaluating the conditions and saving them to variables, then go with your example: duplicating blocks of code is worse than reading a variable twice (most of the time, it's more important to have code that you can understand and maintain instead of trying to "optimize" it when you haven't measured that it's a bottleneck).

DarkDust
  • 90,870
  • 19
  • 190
  • 224
0

You want to run block A when condition A, followed by block B when condition B and so on. With one exception: When no criteria is met then execute the NONE block. Right? Then:

if( !A && !B && !C && ...)
{
  run NONE-BLOCK;
}
else
{
  if( A ) run A-BLOCK;
  if( B ) run B-BLOCK;
  if( C ) run C-BLOCK;
  ...
}
Thorsten Kettner
  • 89,309
  • 7
  • 49
  • 73
  • Worst case this would test all variables twice, best case it's just a little worse than the control structure in the question. – Jonathan Mee Feb 07 '14 at 12:43
  • @ThorstenKettner: So you probaby do not answer the question, don't you? – alk Feb 07 '14 at 12:58
  • I think I do. Jonathan Mee is "looking for a control structure to deal with potentially multiple blocks of code or a NONE block". His approach is efficient, but lacks readability (especially when it is not only two conditions and blocks to deal with). So the answer how to improve it, is how to enhance readability, as this is the only flaw in his code. – Thorsten Kettner Feb 07 '14 at 13:06