|
~ Introduction to Programming: C ~ 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 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==3 – change 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.
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.
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.
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.
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;
}
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 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.
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.
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.