By control flow, we mean the ability to make decisions through programming.
If else
The if else statement is used to branch for either of the conditions. If the expression is true then that particular branch will be followed and the other branch will be ignored.
if (expression)
{
statement 1; /* one direction of the branch */
}else
{
statement 2; /* other direction of the branch */
}
The else condition is entirely optional. I recommend that if else always be written with the braces {} even for simple statements as a good programming practice even though they can be written without it as
if (expression)
statement 1;
else
statement 2;
But what happens when
if (a > b)
if(c < d)
printf("Error");
else
printf("OK");
This is not OK as representation wise the else was supposed to belong to if(a >b) but it ends up paired with if (c < d). So always use braces for control flow statements as it will make your life that much simpler in avoiding unnecessary bugs.
Conditional expression
if (a > b){
z = a;
}else{
z = b;
}
can be replaced by the conditional expression
z = (a > b)? a : b;
Here the '?' is the conditional operator. Above statement means the same as the if else block. Many times using a conditional expression leads to more efficient and cleaner code.
The correct way for the above example is
if (a > b){
if(c < d){
printf("Error");
}
}
else{
printf("OK");
}
If else if
The if else if is an extension of the if else statement.
if (expr1){
statement1;
statement2;
...
}else if(expr2){
statement3;
...
}else if(expr3){
statement4;
...
}else{
statement5;
}
It is useful when multiple conditions have to be checked and branching has to be done accordingly. The last else statement acts as a default case when all the previous conditions have failed.
if (a == 1){
printf("Add");
}else if (a == 2){
printf("Delete");
}else if (a == 3){
printf("Update");
}else{
printf("Exit");
}
Switch
The switch control flow can be used to replace the above if else if statement. It leads to much cleaner code. The only condition is that it can act upon checking integral values only in the conditions.
switch (expr){
case result1:
statement1;
...
case result2:
statement2;
...
case result3:
statement3;
...
default:
statement4;
}
The expression should result in an integral type. The result will branch into any of the cases specified. It should be noted that the flow will drop through cases by default. Hence a break statement is required to get out of the case. This is better shown by the example below:
switch (a)
{
case 1: /* fall through */
case 2: /* fall through */
case 3: /* fall through */
case 4:
printf("Number less than 5");
break;
case 5:
printf("Number is 5");
break;
default:
printf("Number greater than 5");
break;
}
Care should be taken to mention fall through explicitly to avoid unwanted bugs. Also a default case should be placed to handle "the never will happen" situations which unfortunately in most software quite often "do happen".
While and do while loop
while (expr){
statement1;
statement2;
...
}
The while loop will continue execution of it's control block till the expression evalutes to false. The do while will also continue till the expression evaluates to false. But the difference is that do while will execute the body of the loop at least once.
do{
statement1; /* execution of the loop at least once */
statement2;
...
}while (expr);
The while can also be used for an endless loop as
while (1){
statement;
...
}
The for loop
The for loop is quite useful when the need is to iterate a particular sequence of numbers that we know.
for(initialization; condition; increment)
{
statement;
...
}
for(i=0; i<100; i++)
{
printf("Number %d\n", i);
}
The for loop above is similar to the while below
i = 0;
while (i < 100){
printf("Number %d\n", i);
i++;
}
Break, continue and goto
We have already seen the break statement used in the switch statement. Break can be used to exit from the do, while and for loops as well as from switch.
while (a > 100){
i++;
if(i > THRESHOLD){
break; /* this will cause the execution to come out of the loop */
}
}
Continue statement can be used to continue the next sequence of the loop by ignoring the next few statements as shown.
while (a > 100){
i++;
if(b == 0){
continue; /* after this, execution will return to test the while expression. b-- will not be executed.*/
}
b--;
}
Finally we have the dreaded goto statement which can be used to branch anywhere in the function where the label is specified.
while (a > 100){
i++;
if (a > i){
goto err; /* causes execution to jump out of the loop to the statement following the err label */
}
}
err:
printf("error");
Goto is to be avoided being used frequently as it can cause nasty jumps in the code reducing code readability and creating confusion. A particular case where goto is useful is if we have a lot of nesting of the loops and we need to come out of it in case of an error. Break will not work in this case.
for(i=0; i<100; i++){
for(j=5; j>200; j--){
if(error condition){
goto err;
}
}
}
err:
printf("Unable to continue due to error");
Related Posts:
Tags: C, program