~ Introduction to Programming: C ~

Session 3 - Looping & Branching

<<  Back to Contents Page

Session 3– Looping & Branching

In this session we will take a look of making decisions within our programs using loops (to perform a task repeatedly) and branching (to choose whether to perform one task or another.

By the end of this session you should understand how to use while, for and do loops, and also how to use if, switch and the question-mark operator to perform tasks based on the result of a decision.

Conditions

Conditions in C are similar to Pascal. They are the basis for making a decision and are used by both looping and branching instructions, for deciding whether to take one path or another in your program (branching) or whether to stay within or exit a repeated set of instructions (looping).

For a statement to evaluate to true then it must state something that is correct at that point in the program.

The operators used in C are listed below. The first column gives the condition, the second column gives an example that will print a result, the third column will print out no result, as the conditions evaluate to being false.

Condition

true example

false example

i==j           (i is equal to j)

int i=1, j=2;

if(i==1) printf(“true”);

if(i==(j-1)) printf(“true”);

int i=1, j=2;

if(i==2) printf(“true”);

if(i==j) printf(“true”);

i!=j      (i is not equal to j)

int i=1, j=2;

if(i!=j) printf(“true”);

if(j!=1) printf(“true”);

int i=1, j=2;

if(i!=(j-1)) printf(“true”);

if(i!=1) printf(“true”);

i<j           (i is less than j)

int i=1, j=2;

if(i<j) printf(“true”);

if(i<2) printf(“true”);

int i=1, j=2;

if(j<i) printf(“true”);

if(j<2) printf(“true”);

i>j        (i is larger than j)

int i=1, j=2;

if(i>(j-2)) printf(“true”);

if(j>1) printf(“true”);

int i=1, j=2;

if(i>j) printf(“true”);

if (i>1) printf(“true”);

i<=j           (i less than or

                       equal to j)

int i=1, j=2;

if (i<=j) printf(“ue”);

if (i<=(j-1)) printf(“true”);

int i=1, j=2;

if(j<=i) printf(“true”);

if(j<=3) printf(“true”);

i>=j      (i is greater than

                  or equal to j)

int i=1, j=2;

if (i>=(j-1)) printf(“true”);

if (j>=0) printf(“true”);

int i=1, j=2;

if (i>=j) printf(“true”);

if(i>=2) printf(“true”);

(c1)&&(c2)   (condition 1

      AND condition 2 are

                       both true)

int i=1, j=2;

if ((i==1)&&(j>i)) printf(“true”);

if ((j==2)&&(i<j)) printf(“true”);

int i=1, j=2;

if ((j==2)&&(i>j)) printf(“true”);

if ((i==1)&&(j>2)) printf(“true”);

(c1)||(c2)      (condition 1

         OR condition 2 are

                       both true)

int i=1, j=2;

if ((i==1)||(j>i)) printf(“t”);

if ((i==1)||(j<i)) printf(“t”);

int i=1, j=2;

if ((i==j)||(i>j)) printf(“T”);

if ((i<>1)||(j>=i)) printf(“t”);

 For example, if i=1 and j=2 then the condition (i<j) is true because (1<2) is true (i.e. 1 is less than 2). However (i>j) is false because (1>2) is false (i.e. 1 is greater than 2 is incorrect).

 Type out the following listing which should give you an idea of the different possibilities.

#include <stdio.h>

#include <conio.h>

 

void main() {

  int i = 1, j=2;

 

  printf("i is %d, j is %d\n",i,j);

  if (i==1) printf("i==1\n"); else printf("i!=1\n");

  if (j=3) printf("j!=0\n"); else printf("j=0\n");

  if ((i==1)&&(j==3))

    printf("(i==1)&&(j==3)\n");

  else printf("(i!=1)||(j!=3)\n");

  if ((i==1)||(j==1))

    printf("(i==1)||(j==1)\n");

  else printf("(i!=1)&&(j!=1)\n");

  if ((i!=2)&&(j>2))

    printf("(i!=1)&&(j>2)\n");

  else printf("(i==1)||(j<=2)\n");

  if ((i<1)||(j>=3))

    printf("(i<1)||(j>=3)\n");

  else printf("(i>=1)&&(j<3)\n");

  printf("Value of  true:%d, Value of i<>j:%d\n",true,i!=j);

  printf("Value of false:%d, Value of i==j:%d\n",false,i==j);

  getch();

}

 The output should look something like this. Try to match the output to what’s going on in the source code (program):-

i is 1, j is 2

i==1

j!=0

(i==1)&&(j==3)

(i==1)||(j==1)

(i!=1)&&(j>2)

(i<1)||(j>=3)

Value of  true:1, Value of i<>j:1

Value of false:0, Value of i==j:0

 You should notice that the line:-

  if (j=3) printf("j!=0\n"); else printf("j=0\n");

gives a strange output – it seems to check that j is equal to 3. As j is set up as 2 you would expect this to be false, and thus printf(“j=0\n”); should be executed. But in fact, printf(“j!=0\n”); is executed. Why is this?

The statement j=3 ASSIGNS the value of 3 to the variable j whereas if we wanted to test equality, we should have used j==3change the program so that it shows this instead, and it should then work correctly.

If you look carefully at the source code (program), there is a warning message at the bottom of the window stating that there is a Possibly incorrect assignment – double-click on this, and it will take you to the source of the problem. Normally, we wouldn’t want to assign a variable in this manner, so chances are we meant to use == instead – hence the warning message.

So what happens when we use the assignment operator instead? j is given the value of 3 and the value returned from this is 3 – i.e. the value assigned. Thus if we said if((j=3)==3) this would evaluate to true.

You can see in the last two lines of the listing that true is given the value of 1 (or non-zero) as default. Thus, any value that is non-zero will be treated as true in a condition. You can also see that false is given the value of 0 (or zero). Thus if we had assigned 0 to j it would have evaluated to false – e.g. if(j=0) printf(“T”); else printf(“F”); would print out F onto the screen.

More on the IF statement

The IF statement is used to do something if a condition evaluates to true and optionally, you can follow the command with an else statement to show what should happen if the statement evaluates to false.

Here’s a few simple examples as a program

#include <stdio.h>

#include <conio.h>

 

void main() {

  int i = 1, j=2;

 

  if (i==1) printf("Hello\n");

 

  if (i==2) printf("Hello\n"); else printf("Goodbye\n");

 

  if (i==1)

    if (j==2)

      printf("Hello\n");

 

  if (i==1)

    if (j==1)

      printf("Hello\n");

    else {

      printf("Goodbye\n");

      j=1;

    }

 

  if (j==2)

    if (i==1)

      printf("Hello\n");

    else

      printf("Goodbye\n");

  else

    printf("Wow\n");

  getch();

}

 The results of this are as follows:-

Hello

Goodbye

Hello

Goodbye

Wow

 If you expected the last word to be Hello, check the previous instruction, which uses the curly braces to group together two instructions after the else clause, which changes j from 2 to 1.

The switch option

A much simpler-to-use branching instruction is the switch...case statement.

This is designed to look at the value of a variable, and perform different tasks depending on the value.

For example, you could use it to give a menu of choices (e.g. Stone, Knife and Paper) and perform a task based on whichever choice was chosen. Type out the listing below for an example of how to use it:-

#include <stdio.h>

#include <conio.h>

 

void main() {

 

  char ch;

 

  printf("Choose from:-\n[S]tone\n[K]nife\n[P]aper\n");

  ch=toupper(getch());

 

  switch(ch) {

    case 'S' : printf("Stone"); break;

    case 'K' : printf("Knife"); break;

    case 'P' : printf("Paper"); break;

    default  : printf("What was THAT!?");

  }

 

  getch();

}

When you run it, it doesn’t work. It doesn’t recognize the toupper keyword. This is because it is in a different library, so we will need a different include for it. To find out what the library is, click the mouse inside the toupper keyword in the listing, hold down the Ctrl key and press F1. Help will be given on this keyword. You will see that it is in the ctype.h library.

Add another #include preprocessor command below the other two to include this library. The program should now work.

The results are as follows (example shows user pressing P) : -

Choose from:-

[S]tone

[K]nife

[P]aper

Paper

The program will prompt the user to enter S or K or P for Stone, Knife or Paper, and convert the result into an upper case character, storing it in the ch character variable.

That variable is then put into the switch statement, and each case command say what to do if that particular key was pressed. The default  clause says what to do if it was none of the above.

Notice the use of the break; keyword. This stops execution from continuing to the next line beneath, and carries on after the end of the switch statement. Try taking out all of the break; keywords, and you’ll see the effect. For example, pressing S gives you this result :-

Choose from:-

[S]tone

[K]nife

[P]aper

StoneKnifePaperWhat was THAT!?

This may seem pointless, but take a look at the for statement later for an example of how this can be utilised.

The while loop

As in Pascal, the while loop will perform a task repeatedly while a condition holds to be true. The conditions can be as we described earlier.

For example, just say we wanted to create a program that gives the twelve days of Christmas starting at a value chosen by the user. We may want to apply some validation (i.e. checking) to make sure the user enters a value between 1 and 12. Here’s how we would do it:-

#include <stdio.h>

#include <conio.h>

#include <ctype.h>

 

/* Define Prototype for function so it

** can be used before it is implemented

*/

int get_day();

char *get_day_word(int day);

 

/* Main program */

void main() {

 

  int day_of_christmas;

 

  printf("Days of Christmas\n");

  printf("-----------------\n\n");

 

  day_of_christmas = get_day();

 

  printf("On the %s day of Christmas\nMy True Love sent to me:",

         get_day_word(day_of_christmas));

 

  switch(i) {

    case(12): printf("Twelve Drummers drumming\n");

    case(11): printf("Eleven Pipers Piping\n");

    case(10): printf("Ten Lords a-Leaping\n");

    case(9) : printf("Nine Ladies Dancing\n");

    case(8) : printf("Eight Maids a-Milking\n");

    case(7) : printf("Seven Swans a-Swimming\n");

    case(6) : printf("Six Geese a-Laying\n");

    case(5) : printf("Five Go-ooooold Rinnngggsss...\n");

    case(4) : printf("Four Calling Birds\n");

    case(3) : printf("Three French Hens\n");

    case(2) : printf("Two Turtle Doves\n");

    case(1) : if(day_of_christmas>1) printf("And ");

              printf("A Partridge in a Pear Tree");

  }

 

  getch();

}

 

/* get day between 1 and 10 from keyboard */

int get_day() {

  int day = 0;

  while ((day<1)||(day>12)) {

    printf("Choose a day of Christmas from 1-12: ");

    scanf("%d",&day);

  }

  return day;

}

 

/* get number in words */

char *get_day_word(int day) {

  switch(day) {

    case(1)  : return "first";

    case(2)  : return "second";

    case(3)  : return "third";

    case(4)  : return "fourth";

    case(5)  : return "fifth";

    case(6)  : return "sixth";

    case(7)  : return "seventh";

    case(8)  : return "eighth";

    case(9)  : return "ninth";

    case(10) : return "tenth";

    case(11) : return "eleventh";

    case(12) : return "twelfth";

    default  : return "something elseth";

  }

}

 In this example, we have used a function called get_day() to do the deed of obtaining a day number from 1 to 12. In this function, we have defined a while loop, which says that whilst the variable day (which starts off with a value of 0) is less than 1 (which it is to start with) or is larger than 10, then do the commands between the curly braces { and }.

So, the user enter a day number into the variable day via the scanf command, and the condition is attempted again. If the user type in a number from 1 to 10, then the condition is now false, so the loop exits. Otherwise, the loop will be executed again.

Following this, the value returned from the function is the contents of the day variable.

When you run this, try values such as 0 and 13 (should stay in the loop) and (say) 5 – should exit from the loop.

Also try a value of (say) 5.5 – the screen will go mad – break out of it by holding down the Ctrl key and pressing C.

What happened is that what you typed did not conform to what the program was expecting, so it exited after reading the initial 5, leaving .5 to be read. So next time around the loop, it hit the waiting .5 again, and as this does not conform, it goes round again and again etc. forever.

The way to get around this is to flush the keyboard buffer (also known as the stdin stream) so that after exiting, if there’s anything left over, it should be cleared out. To do this, change the following lines as shown in bold:-

    scanf("%d",&day); fflush(stdin);

 Now if you try typing in 5.5 into the program, it will take the first part, and assume you just meant 5.

 Note that this program uses a function that returns a string value. To do this, we need to return a value of char * - this will be explained in a future session on pointers, strings and character arrays.

 You may also notice that this function get_day_word also uses the switch statement without any break; commands. This is OK, because as soon as a value is returned, the function is terminated, so no further commands will be executed in the switch statement, so no need for break;s.  Also note, that in order to show all of the days of Christmas up to the chosen one, we have used a switch statement without break;s. Thus the first case that matches the day number will be executed, and all of the commands afterwards too.

Make sure you save this program, as we will be amending it later.

The do loop

Similarly the do loop will repeat commands in the same way as a normal while loop, except the condition is tested after the commands have been executed once. Note that the do loop is the C equivalent to the repeat...until loop in Pascal, except the end condition is the reverse – it says what to do to stay inside the loop, whereas in Pascal the until condition says what to do to exit the loop.

As an example, the function in the program above could be re-written as follows. There is little difference, other than the fact that we have removed the need to set the day variable to 0 to start with :-

/* get day between 1 and 10 from keyboard */

int get_day() {

  int day;

  do {

    printf("Choose a day of Christmas from 1-10: ");

    scanf("%d",&day);

  } while ((day<1)||(day>10));

  return day;

}

Break and Continue

If you include the break; command inside any loop, it will cause processing to go immediately to the line after the end of the loop – i.e. it will break out of the loop.

If you include the continue; command inside a loop, it will cause processing to go to the end of the loop, for the condition to tested, and the loop to be continued from the top again – i.e. it finishes the current loop, and continues with the next cycle around.

For example, the following is another method of checking whether a user has entered 'Y' or 'N' and looping around until one of these keys has been pressed.

while(true) {

  printf("Press Y or N: "); ch=toupper(getch()); printf("%c\n",ch);

  switch(ch){

    case('Y'):printf("Yes"); break;

    case('N'):printf("No"); break;

    default  : continue;

  }

  break;

}

The for loop

The for loop in C performs the same function as the for loop in Pascal, but looks a lot different!

Take the example line below:- 

for(int i=1;i<=10;i++) printf("i is %d\n");

This will count from 1 to 10 using the i variable. 

A for statement takes the general form:-

for (var initialisation;condition on var;increment on var) instruction;

So the var initialisation part creates a new integer variable called i and sets it to 0 (zero). This will be used for the counting.

The condition on var part is the condition that must be true in order for the instruction to be executed. If it is false, then the instruction is not executed, and the program continues on the next line after the for statement.

So in this case, to execute the command, the i variable must be less than or equal to ten.

Finally, the i++ command is the instruction to run after the instruction has been executed. If you remember, this is a special instruction that means “add 1 to i” or “increment i”. You could also use i=i+1 or i+=1, but i++ is the accepted standard when using for loops.

So what if you wanted to count backwards from 10 to 1? Try this:-

for(int i=10;i>=1;i--) printf("i is %d\n");

The var initialisation part creates a new integer variable called i and sets it to 10. The condition on var part says the to execute the instruction, the i variable must be larger than or equal to 1. Finally, once the instruction has been executed, the loop counter i is decreased by 1 or decremented – this is what i— means. We could have used i=i-1 or i-=1 but i—is the standard way of counting backwards in for loops in C.

The program typed earlier can be amended so that we see the twelve days of Christmas starting from day 1, up to day 12, without the user typing in a specific day.

#include <stdio.h>

#include <conio.h>

#include <ctype.h>

 

/* Define Prototype for function so it

** can be used before it is implemented

*/

int get_day();

char *get_day_word(int day);

 

/* Main program */

void main() {

 

  for(int day_of_christmas=1;day_of_christmas<=12;day_of_christmas++) {

 

    printf("Days of Christmas\n");

    printf("-----------------\n\n");

    printf("On the %s day of Christmas\nMy True Love sent to me:\n",

           get_day_word(day_of_christmas));

 

    switch(day_of_christmas) {

      case(12): printf("Twelve Drummers drumming\n");

      case(11): printf("Eleven Pipers Piping\n");

      case(10): printf("Ten Lords a-Leaping\n");

      case(9) : printf("Nine Ladies Dancing\n");

      case(8) : printf("Eight Maids a-Milking\n");

      case(7) : printf("Seven Swans a-Swimming\n");

      case(6) : printf("Six Geese a-Laying\n");

      case(5) : printf("Five Go-ooooold Rinnngggsss...\n");

      case(4) : printf("Four Calling Birds\n");

      case(3) : printf("Three French Hens\n");

      case(2) : printf("Two Turtle Doves\n");

      case(1) : if(day_of_christmas>1) printf("And ");

                printf("A Partridge in a Pear Tree");

    }

    printf("\n\nPress a key [X to exit]: ");

    if(toupper(getch())=='X') break;

    clrscr();

  }

  printf("... and you try fitting all that into a two-bedroomed flat.");

  getch();

}

 

/* get number in words */

char *get_day_word(int day) {

  switch(day) {

    case(1)  : return "first";

    case(2)  : return "second";

    case(3)  : return "third";

    case(4)  : return "fourth";

    case(5)  : return "fifth";

    case(6)  : return "sixth";

    case(7)  : return "seventh";

    case(8)  : return "eighth";

    case(9)  : return "ninth";

    case(10) : return "tenth";

    case(11) : return "eleventh";

    case(12) : return "twelfth";

    default  : return "something elseth";

  }

}

Press the X key at any time to break out of the loop.

The Question Mark and Colon Operator

You can include conditional if-type statements within mathematic expression using the following structure:-

    (condition) ? expression1 : expression2

 where if the value of (condition) evaluates to be true then expression1 is returned in the expression, otherwise expression2 is returned. This was used in the Session 1 Stone Knife Paper example.

 Here’s a few code snippets:-

printf("Square root of %d is %d",num,(num==4)?2:(num==9)?3:(num==16)?4:0);

printf("You chose %s\n",(ch=='S')?"Stone":(ch=='K')?"Knife":"Paper");

printf("There %s %d item%s here",(num==1)?"is":"are",num,(num!=1)?"s":"");

 See if you can work out what they do.

Exercises

If you have time at the end of the session, or you would like to do some further work at home, you may like to try some of these exercises:-

 1.      Write a program that counts from 1 to 10 working out the squares of each number (i.e. the number times itself) – e.g. the square of 1 is 1, the square of 2 is 4, the square of 3 is 9 etc.

2.      Read an integer from the keyboard, and if the number was less than 0 print a message saying the number is negative, if the number is 0, print a message saying the number is zero, otherwise print a message saying the number is positive.

3.      Using the rand() function described last week, display ten random numbers between 1 and 20 (using a for loop), and add them up in a variable (declared before the for loop) as you go along. Show the total on the screen at the end.

4.      Take the program from exercises 3, and instead of showing the total on the screen at the end, choose a random number from –20 to 20 - do this be using the expression (rand()%41)-20)   - and subtract this from the actual total, storing it in a different variable. Show this value on the screen, and ask the user if they think it is higher, lower, or equal to the real answer by pressing H or L or E. Check if they got the answer right or wrong.

5.      Use a do...while loop to check at the end of the above game whether the user wishes to have another game. If they answer Yes (press Y) then loop back to the beginning, otherwise terminate the game.

6.      Extend this to give a score and high score. A correct answer earns 1 point, an incorrect answer earns –2 points. Game Over if the score reaches 0 after the game.

7.      Try writing a JSP diagram for your program. Try doing a test plan to see if it works.