What is a readable way to code a nested binary branching logic - c++

I have a few logic that looks like
if(a){
if(b){
if(c){
//do something
}else{
//do something
}
}else{
if(c){
//do something
}else{
//do something
}
}else{
if(b){
if(c){
//do something
}else{
//do something
}
}else{
if(c){
//do something
}else{
//do something
}
}
What is the best way tot implement this into readable logic? I dont want to do some big OOP surgery to make it readable because the do something is just one liner. Solution in C/C++ is appreciated

Since the conditions are boolean, and apparently independent, treat them as bits in a word and switch on them:
#include <cstdio>
#define COMPOSE(a,b,c) ( ((!!(a)) << 2) | ((!!(b))<<1) | (!!(c)) )
int f(int i, int j, int k) {
switch(COMPOSE( i==j, i+j<k, k!=42)) {
case COMPOSE(true, true, true):
printf("yo\n");
break;
case COMPOSE(true, true, false):
printf("ye\n");
break;
case COMPOSE(true, false, true):
printf("ya\n");
break;
}
}
int main () {
f(1,1,1);
}

If all //do something are fundamentally different, you don't have much choice (afaik).
For code style I would prefer
if ( a && b && c )
{
}
else if ( a && b && !c )
{
}
else if ( a && !b && c )
...
This removes the necessity of multiple levels of indentation and makes it clear which condition is actually satisfied.
Side note: obviously a && b && !c can be stated as a && b because !(a && b && c) and the use of else if. I would leave it there anyway because the compiler might optimize it and the code looks cleaner.

Related

Can somebody tell me how this code working with no curly braces between two if?

If I am enclosing the code after first if upto second return in curly braces it is not giving me desired output.
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
return (a.score < b.score)? -1:1;
}
Your code has if() and else statements. Each will execute one line of code that comes after them. This means that it will only execute a single statement and end after the first ; that it finds.
for() loops, while() loops, if-else blocks can be used without curly braces if the statement you want to execute consists of only one line of code following them.
Your code works as -
static int comparator(Player a, Player b) {
// if statement without braces- means just one statement executes
if(a.score == b.score)
// Remember if-else will be considered as a single code block so both will run
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
// This statement will run only when the above if condition is not satisfied
return (a.score < b.score)? -1:1;
}
This can be considered to be same as -
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
NOTE : It is generally better if you use the braces as it will be good for readability as well as maintainability of the code. There can actually be two way of parsing it - Dangling else(though most compiler will associate the else with closest if).
In this coding style, there's no way to differentiate between below two code -
if(condition1)
if(condition2)
foo1();
else
foo2();
and,
if(condition1)
if(condition2)
foo1();
else
foo2();
Since, in C/C++, it doesn't consider the indentation in code, so it might create ambiguity while reading the code. So its always better to use curly braces instead of doing it like above. Drop them only when you have a single line and it won't create any confusion reading the code later on...
Hope this helps !
Without curly braces, only the next statement is executed. With proper indentation it becomes easier to see what's going on:
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name) ? -1 : 1;
return (a.score < b.score) ? -1 : 1;
}
This is actually the same as:
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
You have maybe used the braceless else variant without noticing it when writing something like:
if(condition) {
//
} else if(another_condition) {
//
} else {
//
}
Which is actually the same as
if(condition) {
//
} else {
if(another_condition) {
//
} else {
//
}
}
Without curly braces, the if guard only applies to the immediate next statement.
It's just how the language works. :/

Else for multiple if's

Is it possible to make multiple if's and one else for all of them without using the bool variable? I'm talking about something that works like this:
bool triggered = 0;
if (condition)
{
//code
triggered = 1;
}
if (condion2)
{
//code
triggered = 1;
}
if (!triggered)
{
//code
}
So if none of these if's happened - something happens. In pseudo-code I would write it like this:
{
if()
{
}
if()
{
}
}
else
{
}
Is there a possibility to make something similar?
No, you can't do it like that. You can do:
if (condition1 || condition2) {
if (condition1) {
//code
}
if (condition2) {
//code
}
} else {
// code
}
But this means you have to test condition1 and condition2 twice. And if there are lots of conditions, the first if will be very long.
I find your code with the triggered variable preferable. Often, there's already a variable that serves the purpose. For instance, form validation code often looks something like this:
std::string errors;
if (field1 is invalid) {
errors += "Field1 is invalid\n";
}
if (field2 is invalid) {
errors += "Field 2 is invalid\n";
}
if (errors == "") {
// process the form
} else {
// display error message
}

Refactor several nested if with same else

This is not about an existing piece of code but I'm looking for some pattern that may exist in the case that some nested if perform the same thing in their else statement.
if(condition1(a)) {
doSomethingWith1(a);
if(condition2(a)) {
doSomethingWith2(a);
} else {
elseFn();
}
} else {
elseFn();
}
The doSomethingWith... functions are changing the value of a, making it complex to have all the condition in one if.
So I'm just wondering if there is a clearer way to write it (in C, if possible).
Thanks guys
in your case, looks like the first if, if(condition1(a)), is absolutely necessary to test for the value of a before calling doSomethingWith1(a); to avoid an exception. so, no, there is no other way to do it.
if(condition1(a)) {
doSomethingWith1(a);
if(condition2(a)) {
doSomethingWith2(a);
} else {
elseFn();
}
} else {
elseFn();
}
You could just keep a count of the "doSomethings" and invoke the elseFn unless all were executed.
int count = 0;
if (condition1(a)) {
doSomethingWith1(a);
count++;
if (condition2(a)) {
doSomethingWith2(a);
count++;
if (condition2(a)) {
doSomethingWith2(a);
count++;
}
}
}
if (count < 3) {
elseFn();
}
I find it more readable, though less efficient, to double-check the first condition. This refactoring eliminates nesting, without multiple functions. It also more clearly shows three distinct paths of execution by grouping each logical path into a single code block.
if (condition1(a) && condition2(a)) {
doSomethingWith1(a);
doSomethingWith2(a);
}
else if (condition1(a)) {
doSomethingWith1(a);
elseFn();
}
else {
elseFn();
}
I don't know in C but in Java you could write this as the following:
void function(int a) {
boolean b1 = condition1(a);
if (b1) {
doSomethingWith1(a);
boolean b2 = condition2(a);
if (b2) {
doSomethingWith2(a);
}
}
if (b1 || b2) {
return;
}
elseFn();
}

Nested IF statements vs IF-ELSE

I'm learning C language usnig Turbo C++ compiler and just in time I encountered the two statements:
IF (nested with many IFs)
IF-else(not nested but continuing else,else and so on)
I was wondering if my idea is correct or not that IF (nested with many IFs) and IF-else(not nested) are the same? Suggestions are well appreciated.
That's only basic logic behind that:
Nested if conditions:
IF first condition's value is true, go into the second condition.
if(a > 0)
{
printf("A is greater than 0\n");
if(a > 2) printf("A is greater than 0 and 2\n");
}
if-else condition:
IF first condition's value is false, go to the next:
if(a > 0) printf("A is greater than zero\n");
else if(a < 0) printf("A is lesser than zero\n");
else printf("A is zero\n");
There is one more instruction that you should know, switch:
switch(a)
{
case 0: printf("A is zero\n"); break;
case 1: printf("A is one\n"); break;
case 5: printf("A is five\n"); break;
default: printf("A is not 0, 1 or 5\n"); break;
}
Nested if is not equivalent to if-else. It can be equivalent to single if with a combined condition, for instance:
if (a == 1) {
if (b == 2) {
...
}
}
is equivalent to:
if (a == 1 && b == 2) {
...
}
I guess you rather mean if this:
if(expression){
//code
}
else{
if(expression){
//code
}
}
is equivalent to this:
if(expression){
//code
}
else if(expression){
//code
}
and yes it's absolutely the same. Second one is just better looking way of doing this.
The else if blocks are in fact nested else’s since C and C++ don’t have any special support for “elseif” or “elif” concept (not speaking about the preprocessor directives now). It gets obvious with strict use of blocks and indentation:
if(something) { doSomething(); }
else {
if(anotherThing) { doAnotherThing(); }
else {
if(yetAnotherThing) { doYetAnotherThing(); }
else
{ doSomethingElse(); }
}
}
The same code written with the usual else if notation:
if(something) { doSomething(); }
else if(anotherThing) { doAnotherThing(); }
else if(yetAnotherThing) { doYetAnotherThing(); }
else { doSomethingElse(); }
And as Mateusz Kwaśniak has mentioned, you should prefer switch over else if when possible. However, it’s not available for string comparison, for example.

Changing while loop to accommodate two situations

Suppose I have a while loop that depends on two separate inputs. In situation one, the while loop will take the value 1, and in situation two, it should take !cin.eof(). Is there a way I can do this efficiently? To be more concise:
string hello;
cin >> hello;
if(hello == "one")
{
//make the while loop depend on value 1
}
else if(hello == "two")
{
//make the while loop depend on value !cin.eof()
}
while(/*depends on above conditional*/)
{}
I don't want to do something like:
if(hello == "one)
{
while(1){}
}
else if(hello == "two")
{
while(!cin.eof){}
}
because the while loop essentially does the same thing in each situation.
For readability and in the interest of cohesion, I think you should move the contents of your loop into a separate function:
void DoSomething() { /* ... */ }
// ...
if(hello == "one)
{
while(1){ DoSomething(); }
}
else if(hello == "two")
{
while(!cin.eof){ DoSomething(); }
}
It's easier to see that the different while loops are doing the same thing but their conditions are different.
I believe you're looking for something like this:
while((hello == "one") || (hello == "two" && !cin.eof)) {
}
This code will do what you want, because it checks 'is the variable "one"? If so, keep executing. If it's not, it'll check: Is the variable "two"? If so, it'll check for cin.eof.
If it's neither, the loop won't execute. (the && 1 in the first condition was omitted, because it's always 'true', equalling and infinite loop)
Edit:
To simplify things, you may want to consider this code (as suggested in the comments):
bool HelloIsOne = (strcmp(hello, "one") == 0);
bool HelloIsTwo = (strcmp(hello, "two") == 0);
while(HelloIsOne || HelloIsTwo && !cin.eof) {
}
The brackets, which I placed in the previous example are actually unnecessary, because && binds stronger than ||, but they help the general clarity of the code.
Simply use or (||) as a condition in the while loop. Set the first condition if(hello == "one"). Now you have a while loop that will loop if one of the conditions is true.
bool value = hello == "one";
while (value || !cin.eof) {}
If you're using C++11:
#include <functional>
auto check = (hello == "one") ? []() bool -> { return 1; } :
[]() bool -> { return !cin.eof(); };
while(check) {
};
How about this:
switch(hello)
{
case 'one':
{
for(; 1; );
{
// your loop here
}
break;
}
case 'two':
{
for(;!cin.eof; )
{
// your other loop here
}
break;
}
default:
{
cout << " shouldnt get here unless bad user input" << endl;
break;
}
}
You can do something like this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string hello;
cin >> hello;
while(hello=="one"?1:(!cin.eof()))
{
//do stuff
}
return 0;
}
It checks if the string hello is "one" and if it's true, the condition of the while is 1, else it is !cin.eof() as you wanted.