質問

I have reasonably complicated logic for if statements. I am currently using:

if(numerical_evaluation) {

    if ((!boolOne && boolTwo) || !boolThree){
        //do stuff
    }
}

where boolOne, boolTwo, and boolThree are logical operations (perhaps x < y or 'myObject->getBool' etc).

I do not know a better way to make this easily readable without nesting the || condition within a third if statement.

The reason I am having difficulty is that the or operator makes it such that it seems a third if statement might be warranted.

One option would be to do this.

Or, I could do something like

if(x <= y) {

    bool boolFour = false;
    if ((!boolOne && boolTwo))
        boolFour = true;

    if (boolFour || !boolThree){
        //do stuff
    }
}

Maybe even make a separate function to try to validate everything or combinations into a single return value?

Alternatively, I could attempt to restructure the code in such a way this is not required, which may require significant amounts of time to do.

My question: What is the best way to format complicated if questions - which include more complicated evaluations than just if (!A && B && C) variations? It seems things get hopelessly unreadable (especially when you have complicated evaluations for boolOne, boolTwo, etc) when you include || statements in combination with && statements into one line. Do the same principles from - Best way to format if statement with multiple conditions - apply here too or are there fundamental differences when using a variety of logical operators?

役に立ちましたか?

解決

This:

bool boolFour = false;
if ((!boolOne && boolTwo))
    boolFour = true;

can be expressed much more clearly as:

bool const boolFour = !boolOne && boolTwo;

By giving boolFour a good, descriptive name, this approach of breaking down complex expressions and naming subexpressions can make code much more readable, much easier to understand, and much easier to debug.

If a complex expression is used in multiple places, a function should be used to encapsulate the common logic. If the expression is only used in one place, though, it is preferable to break up the expression locally and use named const variables, to keep the logic close to where it is used.

他のヒント

Write a helper function that encapsulates the combined boolean checks. E.g:

bool isEligibleForReduction(int age) { return age < 12 || age >= 60; }

if possible I would usually do something like:

if(numerical_evaluation) { 

    meaningful_name = (!boolOne && boolTwo);
    other_meaningful_name = !boolThree;
    if (meaningful_name || other_meaningful_name){ 
        //do stuff 
    } 
} 
if (!numerical_evaluation) {
    // nothing to do.
} else if (!boolOne && boolTwo || !boolThree) {
    // do whatever
}

Of course, as others have said, boolOne, boolTwo, and boolThree aren't very helpful names.

The best way is good use of white space.

if( numerical_evaluation &&
    (
        (!boolOne && boolTwo) ||
        !boolThree
    )
  ) {
        //do stuff
}

It's not exactly pretty, but it's easy enough to follow. You can also use a function to hide the if logic.

bool my_test( int numerical_evaluation, bool boolOne, bool boolTwo, bool boolThree ) {
    return
        numerical_evaluation &&
        (
            (!boolOne && boolTwo) ||
            !boolThree
        );
}

if( my_test( numerical_evaluation, boolOne, boolTwo, boolThree ) ) {
    // do stuff
}

Remember, when it's not a trivial case, use comments to give people an idea of what you're testing (no need for comments that just explain C++ syntax). Even if they can read your if logic just fine, it lets them double check it. Good comments can quickly give people an overview of your program and much of the logic, without reading unnecessary details or any code.

Although it was a performance suggestion, complicated boolean expressions are sometimes better represented as a table lookup.

Something complicated like:

if( (a && !c) || (a && b && c )) 
{
    category = 1;
}
else if( (b && !a ) || (a && c && !b )
{
   category = 2;
}
else if( c && !a && !b ) 
{
   category = 3;
}
else
{
    category = 0;
}

Becomes:

static int categoryTable[2][2][2] = {
    // !b!c    !bc    b!c    bc
    0,         3,     2,     2,      // !a
    1,         2,     1,     1       // a
};
... 
category = categoryTable[a][b][c];

Code Complete 2 page 614 & 615, "Substitute Table Lookups for Complicated Expressions".

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top