About the exclusiveness of the cases of an if block - c++

I have a question about good coding practices. I understand the differences between doing an if-else if and multiple ifs (that is, when a condition is met in an if-else if, the rest of the checks are skipped). I've found a piece of code along these lines:
if (A == 5) {
do_something();
} else if (B == 7) {
do_something_else();
}
I understand that this code won't check B == 7 if A == 5. The code works, so that means that B is only 7, if A is not 5, but I think this is just waiting to break when the code changes. What I would do is:
if (A == 5) {
do_something();
return or continue or break;
}
if (B == 7) {
do_something_else();
return or continue or break;
}
My question is, when I have multiple exclusive cases that depend on different, exclusive variables, what's the best way to tackle the flow control? I have the impression that the first code (with else ifs) depends a lot on other pieces of code to work, and that changes in other areas might break it. The second one seems to be a bit clunky. A switch could be a third option, but I would need to create another structure to hold the case and the logic to assign its value, and I think that it would be a bit clunky and counter-intuitive.

You asked about "exclusive" cases, but the issue with the conditions A == 5 and B == 7 is that they are not exclusive; they are independent.
For full generality you may need to test and handle all four cases:
if(A == 5) {
if(B == 7) {
/* case 1 */
} else {
/* case 2 */
}
} else {
if(B == 7) {
/* case 3 */
} else {
/* case 4 */
}
}
This is the notorious "bushy" if/else block. It's notorious because it can almost immediately become nearly impossible for a reader to follow, especially if the cases are involved, or more levels are introduced. (I think most style guides will tell you never to use an if/else tree that's 3 or more levels deep. I'd certainly say that.)
I have occasionally used these two alternatives:
(1) Fully decouple the cases:
if(A == 5 && B == 7) {
/* case 1 */
} else if(A == 5 && B != 7) {
/* case 2 */
} else if(A != 5 && B == 7) {
/* case 3 */
} else if(A != 5 && B != 7) {
/* case 4 */
} else {
/* can't happen */
}
The point here is to make it maximally clear to a later reader exactly which conditions go with cases 1, 2, 3, and 4. For this reason, you might as well list the last, else if(A != 5 && B != 7) case explicitly (as I've shown), even though by that point it's basically an "else".
(2) Contrive a "two level" switch. I can't say this is a common technique; it has a whiff of being "too clever", but it's robust and readable, in its way:
#define PAIR(b1, b2) (((b1) << 8) | (b2))
switch(PAIR(A == 5), (B == 7)) {
case PAIR(TRUE, TRUE):
/* case 1 */
break;
case PAIR(TRUE, FALSE):
/* case 2 */
break;
case PAIR(FALSE, TRUE):
/* case 3 */
break;
case PAIR(FALSE, FALSE):
/* case 4 */
break;
}
I wouldn't recommend this when the conditions are A == 5 and B == 7, because when you're down in the switch, it's not obvious what "TRUE" and "FALSE" mean, but sometimes, this sort of thing can read cleanly. It's also cleanly amenable to 3 or more levels of nesting, unlike "bushy" if/else trees, which as I said are notoriously unreadable.

The most robust way of programming this,
while avoiding the assumption that either A==5 or B==7 is to consider all the four cases:
if ((A == 5) && (B == 7))
{
do_somethingAB();
/* or */
do_somethingA();
do_somethingB();
} else if (A == 5)
{
do_somethingA();
} else if (B == 7)
{
do_somethingB();
} else
{
do_somethingNeither();
/* or
do nothing */
}

As I think you know, the two pieces of code are not equivalent. (They're equivalent IF they both contain "return or continue or break", which makes the question more interesting, but that's a different answer.)
In general, which one you choose (or how you choose to rewrite it) has to depend on precisely what you want the program to do.
When you write
if (A == 5) {
do_something();
} else if (B == 7) {
do_something_else();
}
you're additionally saying you want to do_something_else only if A is not equal to 5. That might be just what you want, or it might be a bug. If you wanted to achieve the same effect without an else, it would have to look like this:
if (A == 5) {
do_something();
}
if (A != 5 && B == 7) {
do_something_else();
}
The second piece of code you wrote in your question, on the other hand, has the potential to execute both do_something and do_something_else.
In general, it's best (clearest and least confusing) if all the conditions in an if/else chain test variations on the same condition, not some unusual mixture involving, for example, both A and B.
You use an if/else block when the alternatives are truly and deliberately exclusive, and when you want to emphasize this fact. You might choose to use separate if blocks (not chained with else) when the alternatives are not exclusive, or when they're only coincidentally or accidentally exclusive. For example, I have deliberately written code like
if(A == 5) {
do_something();
}
if(A != 5) {
do_some_unrelated_thing();
}
I might do this when the two things have nothing to do with each other, meaning that in some future revision of the program's logic, they might be not be exclusive after all. Or, I might do this if do_something is not a single like, but is a long, elaborate block, at the end of which I'm concerned that the reader might not have remembered why we were or weren't doing something, and that on the other hand we might want to do something else. For similar reasons, I've occasionally written
if(A == 5) {
do_something();
}
if(A == 5) {
do_some_unrelated_thing();
}
in the case that, again, the two things to be done had nothing to do with each other, and the reasons for doing them might diverge.

[This is now my third answer. The fact that I keep misreading your question, and failing to grasp the essential point you're asking about, suggests that maybe I shouldn't be answering at all.]
I think the essential point you're asking about concerns the case where the cases are independent, but you get the effect of an else due to the fact that each clause contains a control-flow statement which "goes out": a break, or a continue, or a return, or something like that.
In this specific case, my preference today would be not to use the else. When we write
if(A == 5) {
do_something();
return or continue or break;
}
if(B == 7) {
do_something_else();
return or continue or break;
}
it's clear that the two conditions have nothing to do with each other, other than that they're both cases that do something to "finish" the subtask being done, and leave the block of code that's responsible for performing that subtask.
When we write the two cases separately (without an else), we make clear not only that they're independent, but that they could be reordered, or that another case could be introduced in between them, etc.
But then again, could they be reordered? How likely is it that both cases A == 5 and B == 7 will both be true? And in that case, how important is it that do_something be done, as opposed to do_something_else? If the two cases can't be reordered, if it would be wrong to test B first and maybe do do_something_else, I suppose the explicit else is preferable, to tie the two cases together and make even more clear the requirement that A be tested first.
Like any question of style, the arguments for and against this sort of thing end up being pretty subjective. You're not likely to find a single, overwhelmingly convincing answer one way or the other.

One way to handle this is to use a do { ... } while (0); technique.
Here is your original code:
if (A == 5) {
do_something();
} else if (B == 7) {
do_something_else();
}
Doing else if on the same line is [IMO] a bit of a hack because it hides the true indentation:
if (A == 5) {
do_something();
}
else
if (B == 7) {
do_something_else();
}
Using the aformentioned technique, which I've used quite a lot is:
do {
if (A == 5) {
do_something();
break;
}
if (B == 7) {
do_something_else();
break;
}
} while (0);
This becomes even more evident when we increase the number of levels in the if/else ladder:
if (A == 5) {
do_something();
} else if (B == 7) {
do_something_else();
} else if (C == 9) {
do_something_else_again();
} else if (D == 3) {
do_something_for_D();
}
Once again, this is indented to:
if (A == 5) {
do_something();
}
else
if (B == 7) {
do_something_else();
}
else
if (C == 9) {
do_something_else_again();
}
else
if (D == 3) {
do_something_for_D();
}
Using the do/while/0 block, we get something that is simpler/cleaner:
do {
if (A == 5) {
do_something();
break;
}
if (B == 7) {
do_something_else();
break;
}
if (C == 9) {
do_something_else_again();
break;
}
if (D == 3) {
do_something_for_D();
break;
}
} while (0);
Note: I've been programming in c for 35+ years, and I've yet to find a case where a more standard use of do/while (e.g. do { ... } while (<cond>)) can't be replaced more cleanly/effectively with either a standard for or while loop. Some languages don't even have a do/while loop. Thus, I consider the do loop to be available for reuse.
Another use of do/while/0 is to allow things defined by a preprocessor macro to appear as a single block:
#define ABORTME(msg_) \
do { \
printf(stderr,"ABORT: %s (at line %d)\n",msg_,__LINE__); \
dump_some_state_data(); \
exit(1); \
} while (0)
if (some_error_condition)
ABORTME("some_error_condition");

Related

what is the use of if else statements?

I don't quite understand the meaning of else if statements.
why not just to continue with the if statements in case one is false?
it works the same.
example with if only that will work the same with else if:
function testSize(num) {
if (num < 5){
return "Tiny";
}
if (num < 10){
return "small";
}
return "Change Me";
}
testSize(7);
In your actual code you specify a return statement in the code associated to the if statement.
Suppose you don't specify a return statement or suppose today you specify a return statement but tomorrow you remove it to do a common return at the end of the method.
This code will test each condition even if the first one is true :
if (num < 5){
// do something
}
if (num < 10){
// do something
}
This code will not test the next condition if the first one is true :
if (num < 5){
// do something
}
else if (num < 10){
// do something
}
These two ways of doing have two distinct meanings.
When you have a series of if statements, you expect that more than one condition may be true.
When you have a series of if-else-if statements, you expect to have not more than one condition true.
Using the first form (a series of if) while functionally you expect to have not more than one condition true is misleading.
Besides, if the code is modified and you add a condition that is both true for two if statements while you don't want have this case, it would create an issue.
Your code is only showing your belief. What would happen in the example below?
function testSize(num) {
if (num < 5){
x = 1;
}
if (num < 10){
x = 2;
}
result = complex calculations;
}
function testSize2(num) {
if (num < 5){
x = 1;
} else if (num < 10){
x = 2;
}
return x * 2;
}
testSize(4); // result is 4
testSize2(4); // result is 2
x may also be involved in more calculations
if(condition) {...}
if(condition) {...}
if(condition) {...}
In above code, even if the first or second condition is true, third condition have to be checked.
if(condition) {}
else if(condition){}
else if(condition){}
Here if first condition is true, next two will not be checked. So, it saves time and is more readable logically.
A one way if statement takes an action if the specified condition is true.If the condition is false, nothing is done. But what if you want to take alternative actions when the conditions is false ? You can use a two-way if-else statement. The action that a two-way if-else statements specifies differ based on whether the condition is true or false.
Well, there is a bit different from this two statement.Consider the follow samples
if(a > 0) {
...
}
if( a == 0) {
...
}
if(a < 0) {
...
}
and
if(a > 0) {
...
}
else if( a == 0) {
...
}
else if(a < 0) {
...
}
when a is zero the last else if statement will not be execute while if need to compare third time.If a equals to 10, else if could be execute once while if is third.From this else if statement could be execute less and let your program a bit fast.
else if should be used when there are multiple conditions and you want only one of them to be executed, for instance:
if(num<3){ console.log('less than 3') }
else if(num<2){ console.log('less than 2')
If you use multiple if statements instead of using else if, it will be true for both the conditions if num = 1, and therefore it will print both the statements.
Multiple if statements are used when you want to run the code inside all those if statements whose conditions are true.
In your case it doesn't make a difference because the function will stop and return at the very first return statement it encounters. But let's say, the blocks' orders are interchanged, then your function will never return 'tiny' even if num = (anything less than 5).
I hope that helps!
If all your if branches terminate the function (e.g., but returning a value of throwing an exception), you're right, and you really don't need an else statement (although some coding standards might recommend it).
However, if the if branches don't terminate the function, you'd have to use an else or else if clause to prevent multiple blocks from being executed. Assume, e.g., you want to log a message to the console instead of returning it:
if (num < 5) {
console.log("Tiny");
} else if (num < 10) {
console.log("small");
} else {
console.log("Change Me");
}

Arrangement of 2 by 2 condition in if statement in C-family language

When programming, I'm usually dealing with two sets of conditions combined together, like:
if (A && B){...}
else if (!A && B){...}
else if (A && !B){...}
else if (!A && !B){...}
It can also be resolved using nested if statements.
if (A){
if (B) {...}
else {...}
}
else {
if (B) {...}
else {...}
}
EDIT: Some new thoughts, what about I firstly evaluate both A and B and store as temporary variable (then do as the first approach) in case that the evaluation of A and B both have no side-effect?
So my question is there any performance difference between them and what about their readability?
I code in C++, if matters.
The two cases are not the same. In the second case, A and B will each be evaluated exactly once. In the first case, A and B will evaluated a number of times, depending upon their value.
While this almost certainly won't affect the optimization of the typical case, it will matter if A or B have side effects.
There's no way to predict which code generation strategy the compiler will choose in cases like that (and it can actually depend on surrounding context). This makes your question unanswerable in general case. One should normally expect the compiler to be smart enough to recognize the equivalence of both of your constructs (assuming they are indeed equivalent) and choose the most optimal one automatically.
The most optimal code generation strategy might be something else altogether, e.g.
// Assuming A and B are either 0 or 1
switch ((A * 2) + B) {
case 0: ...; break;
case 1: ...; break;
case 2: ...; break;
case 3: ...; break;
}
Just choose whatever makes your code more readable.
It's a hard question; honestly, I think everyone looks at this a little bit differently. As people have mentioned here it does not matter as a compiler should generate the same output for both (should! not necessarily will — it honestly depends on the code).
Yet, for example, let's look at this code:
int Nested(int a)
{
if(a > 0)
{
if( a > 1)
{
if( a % 2 == 0)
{
if( a % 10 == 4)
{
printf("a is valid");
return 1;
}
else
{
printf("a's last digit inst 4");
}
}
else
{
printf(" a is not odd");
}
}
else
{
printf(" a is not bigger than 1");
}
}
else
{
printf(" a is not bigger than 0");
}
return 0;
}
int NotNested(int a)
{
if(a <= 0)
{
printf(" a is not bigger than 0");
return 0;
}
if(a <= 1)
{
printf(" a is not bigger than 1");
return 0;
}
if(a % 2 != 0)
{
printf(" a is not odd");
return 0;
}
if( a % 10 != 4)
{
printf("a's last digit inst 4");
return 0;
}
printf("a is valid");
return 1;
}
I personally think that NotNested in my example is much more readable,
yet it's my personal opinion and both of these functions should do the same.
So yeah, in terms, of readability try to avoid nesting.

Optimized code for two string compare in if condition

I want to do two string compare and used two different if condition. Is there any better way to do string compare in one if condition
if (strcmp(Buff1(), Config1) == 0)
{
if (strcmp(Buff2, Config2) == 0)
{
// my code goes here
}
}
The equivalent code is:
if ((strcmp(Buff1(), Config1) == 0)) &&
(strcmp(Buff2, Config2) == 0))
{
// my code goes here
}
Note: The compiler should generate the same machine code for both code samples. The difference is cosmetic and primarily aimed at the reader of the code.
You do get a difference when you add else clauses:
if (strcmp(Buff1(), Config1) == 0)
{
if (strcmp(Buff2, Config2) == 0)
{
// my code goes here
}
else
{
// else 1
}
}
else
{
// else 2
}
Compared to:
if ((strcmp(Buff1(), Config1) == 0)) &&
(strcmp(Buff2, Config2) == 0))
{
// my code goes here
}
else
{
// Single else clause
}
In addition to Klas's answer(just in case you're not familiar with the AND operator) - the AND operator ('&&') checks the first condition and it continues to check the second condition -only if- the first condition is true.
So in your specific question, it checks if the first couple of strings are equal and only if true (are equal), it checks if the second couple are also equal.
The obvious optimization (not mentioned yet), if you know anything about those strings, is to first perform the compare that is more likely to fail.

C++ if statement notation - Is this equivalent?

I'm 99% sure this won't work but that remaining 1% is bothering me
int x;
//is this if statement
if(x == 1, 5, 7)
{
//do something here
}
//equivalent to this if statement
if((x == 1) || (x == 5) || (x == 7))
{
//do something here
}
No it's totally not equivalent.
if(x == 1, 5, 7)
calls the comma operator, which will effectively end up in the last value because of , has the lowest precedence:
if(7)
since unfolding with parenthesis should look like
if(((x == 1), 5), 7)
while
if((x == 1) || (x == 2) || (x == 7))
checks if x equals either 1, 2 or 7.
They are not equal. When you write it like
if(x == 1, 5, 7)
{
//do something here
}
it basically translates into
if(7)
{
//do something here
}
which will always be true in case the number in the condition block is a non-zero number.
Example 1:
int main()
{
int x=10;
if(x==1,5,7)
cout<<"hello"<<endl;
return 0;
}
Here, the output is "hello", because 7 is treated as a true boolean variable.
Example 2:
int main()
{
int x=10;
if(x==1,5,0)
cout<<"hello"<<endl;
return 0;
}
Here, there is no output because 0 is considered as a false boolean variable.
Regarding a faster solution discussed in the comment section of the OP, here's a 'fast' solution:
If you have a large number of constant comparisons to perform, a switch statement is faster than individual if(x == 1) statements as it is compiled to a branch-table (a kind of hashtable directly within program code, giving it O(1) lookup), however it's possible that existing compilers will already optimize if(x==1||x==2||x==3...) to a branch-table too.
bool xIsInSet = false;
switch( x ) {
case 0: case 1: case 2: case 3:
case 4: case 5: case 6: case 7: // add a case for each literal comparison
xIsInSet = true; // no `break` needed, there's only 1 case.
}
if( xIsInSet ) {
// do stuff
}
This can be inlined to a lambda which is invoked immediately to eliminate xIsInSet:
if( [&x]() -> bool {
switch(x) { case 0: case 1: case 2: case 3: return true; }
return false; }()
) {
// do stuff
}
Unfortunately C++11's variadic templates don't let us dynamically add case statements, and hacking it using a preprocessor #define is possible - if you don't mind using a metaprogramming library. A better alternative might be an inline #include of a file generated by your build script. What would be even neater would be a way to somehow #include the standard-output from another program (e.g. if we could do #include '.\generateCasesFor.sh 1 2 5 10 12', alas not yet).

else if comparison - compiler standpoint

Are these blocks of code identical? By identical I mean, does the compiler interpret them exactly the same way?
int i = 2;
if (i == 0) {
System.out.println("0!");
} else if (i == 1) {
System.out.println("1!");
} else if (i == 2) {
System.out.println("2!");
} else {
System.out.println("?!");
}
int i = 2;
if (i == 0) {
System.out.println("0!");
} else {
if (i == 1) {
System.out.println("1!");
} else {
if (i == 2) {
System.out.println("2!");
} else {
System.out.println("?!");
}
}
}
As you can see this is Java.
While both my friend and I agree that logically these are exactly the same, I was wondering whether the java compiler compiles them exactly the same way. The thing that strikes me is that in the second else/if block you are nesting ifs and elses inside of the else block.
However, given my lack of knowledge in assembly or java byte code, this very well could compile to be completely identical. The only advantage could be syntactical sugar, if you will.
Will someone put this issue to rest - assuming you are extremely confident in the answer (otherwise another debate might ensue).
The two code samples differ only in the use of redundant curly braces, so I would be very suprised if different code is generated. But it's easy enough to check if you are really curious - use the javap command to display the bytecode.