Chapter 3: Moving Around: Branching and Looping
Let's imagine a long listing of computer code, just a bunch of statements one after the other:
statement 1
statement 2
statement 3 ....
and so on. And let's imagine a computer executing the code and stepping through it directly, just going statement 1, statement 2, statement 3 .... The program can do a lot of things going through the code directly, but it could do more interesting things if instead of going one by one it could choose to go to different parts of the code. Maybe it goes statement 3, statement 4, then jumps to statement 7, statement 8 and continues. Or maybe it skips statements 7 and 8 and goes straight to 9. This concept of letting code run in different ways it called branching. Another thing we could have the program do is repeat a few lines of code, instead of going to statements 7, 8, 9, and then to 10 it could repeat 7, 8, and 9. It could execute 7, 8, 9, then repeat it again and again a few times, then go on to line 10. This concept of repeating a series of statements is called looping and is very important to programming. We'll cover branching in the first part of this chapter and looping in the latter part. Specifically we'll do the following.
l Learn about branching in code
l Implement the if-else statement
l Implement the switch statement
l Learn about looping
l Implement the for, while, and do-while loops
Branching
Branching in computer programming means being able to change the direction of code when it executes, skipping some parts of code and executing others based on certain conditions. This is a fundamental concept of all structured programming languages and the most common way to branch code (in all structured languages not just C#), is to use an if statement.
if statement
The idea behind the if statement is simple: when the program goes to the if statement it performs a test. If the test is true the code in the block after the if statement is executed, if the test is false the code is skipped. The syntax is:
if( test )
{
// Code here runs if test is true
}
This works great for many situations. But besides the single if block we can add an else block after the if. The else says that if the test is false we execute the code following the else. The syntax for this if-else statement is:
if( test )
{
// Code here runs if test is true
}
else
{
// If the test was false, code here runs instead
}
Let's make a more complete program that's pretty simple but will give an example of the if statement in action. Create a new Console project and add the following lines of code so the main function looks like the one below:
static void Main(string[] args)
{
int age;
Console.Write("Enter your age: ");
age = Convert.ToInt32( Console.ReadLine() );
if (age > 30)
{
Console.WriteLine("You're over 30.");
}
else
{
Console.WriteLine("You're not over 30 yet");
}
}
Then run the program with Ctrl+F5. The program is pretty straightforward. The first few lines declare the variable age (which stores the user's age) that it gets it from the user. Then the test “age > 30” is done in the if statement and tests if age is greater than thirty. If it is the user is told they're over thirty, if not they are told they're not.
The first question we can ask concerning the if statement is what kind of tests are there? There are several different types of tests we can do, but it all comes down to something that will output the values true or false. These types of tests are inspired by Boolean logic, a type of mathematical logic.
Boolean Tests
Remember in chapter two we discussed the boolean variable type, which can be set to true or false. Well this type can be used for our if tests. Here's a slightly contrived example of a program where at some point we need to decide to draw a triangle or not:
bool drawTriangle;
... // Some code happens to set drawTriangle to true or false
if( drawTriangle )
{
// Draw the triangle
}
We can also use the not operator (an exclamation point in front of the boolean variable) to reverse the true/false for a test. For example:
if( !drawTriangle )
{
// Code here runs if drawTriangle is false
}
// !drawTriangle means not true
Comparison Tests
Besides just tests with boolean variables directly we can do many comparison tests. The most basic tests are with two numbers and we can compare if one is less or greater than the other, just like in basic math. To write things mathematically we can say that for any two numbers A and B we can do the following tests:
if( A < B ) // True if A is less than B
if( A <= B ) // True if A is less than or equal to B
if( A > B ) // True if A is greater than B
if( A >= B ) // True if A is greater than or equal to B
This is the type of test we used in the age program previously. Besides these greater/less than ones we can also test for equality. To test if two numbers are equal we use the equality sign, which is two equal signs:
int A, int B;
// Some code does things with A and B
if( A == B )
{
// Code here runs if A is equal to B
}
So in C# for "equals" we use two equal signs. Note too we use this equality test with integer type numbers, which are whole numbers, but usually not with decimal numbers. The problem with comparing decimal numbers such as float for equality is that they can be unreliable because of precision problems and round off errors. Let's say we have:
float number;
...
// Here number = 0.000000001f
if( number == 0.0f )
{
// This code is skipped, since number doesn't equal zero
}
But in the above case we probably wanted the code inside the if brackets to be executed, since number is very close to zero, but we could easily have a round off error that caused an extra 1 at the end of it that throws the test off. And the equality tests aren't just for numbers, many classes have built in the == for an equals test. For example we could compare if two string are equal with it.
And with the equality test we can also have a test for not being equal. The symbol for this is an exclamation point and an equals sign !=:
int A, int B;
// Some code does things with A and B
if( A != B )
{
// Code here runs if A is not equal to B
}
Remember the exclamation point ! means not true.
The previous tests for the if-statements all used a single test to decide if the code would run or not. But inside the if statement we can combine multiple tests. We do this by using the and, &&, operator and the or, ||, operator.
The and operator says that for the test to be true, all of the conditions must be true. Let's say that we wanted to test if someone's age is between 20 and thirty. This is two tests, one if the age is 20 or more and another if it is less than or equal to 30. We make sure both of these are true by "anding" them together:
if( age >= 20 && age <= 30 )
{
// Code runs here if age is between 20 and 30
}
Now let's say that instead of identifying people between twenty and thirty, we want to identify people who are either pretty young, less than 15, or pretty old, over 85. So we want our if statement to be true if the age is under 15 or over 85, then we'll put an OR, ||, between them (Note: The vertical slash symbol can be hard to find on the keyboard for a lot of people at first, it's the capped of the backslash \ in the upper right corner of the keyboard.) Our if statement will then look like:
if( age < 15 || age > 85 )
{
// Code here runs if age is under 15 or over 85
}
The OR statement will also be true if either of the conditions is true. Unlike the "or" used when were speaking, which usually means just one or the other. For instance, if someone said "I'm going to the grocery store today or tomorrow" we take this to mean that they will go to the store today or tomorrow, but not go the grocery store both today and tomorrow, which is what the computer OR means. As an if statement it would be:
bool gotoStoreToday, gotoStoreTomorrow;
if( gotoStoreToday || gotoStoreTomorrow )
{
// Code here runs if gotoStore today is true, or if
// gotoStoreTomorrow is true,
// or if both of them are true
}
That kind of one or the other OR is called exclusive or, XOR, but it isn't used with these types of test in C#.
Combining Tests
We can combine multiple ANDs and ORs to make tests as complicated as we want. To keep them clear like in mathematics we put parentheses around tests to say which ones go first. Let's say that for whatever reason we are making a program that runs some special code for weekends in December, so we need to test in its code if today is Saturday or Sunday and if the variable month is December.
if( (today == Day.Saturday || today == Day.Sunday) && month == Month.December )
{
// Code here runs if it's a weekend in December
}
The Day.Saturday and Sunday and Month.December are enums, a special way to write values for variables to make them more readable. We won't worry about that for now, let's just look at the tests inside parentheses in the if statement, it tests true if today equals Saturday or Sunday. Then the overall test is true if month is also equal to December. We could add more and more conditionals and these types of tests can become long and complex, but usually they'll be simple, just one or two conditionals.
More on if
Now that we have a pretty good understanding of the kinds of tests we can do inside of the if statement and the basic syntax of it, let's look at a few more little points about the if statement. For starters, if we just want one line to execute if the if is true (or in the else block) we don't need parenthesis, without parenthesis only the first line after the if is run.
if( testIsTrue )
success = true; // Just one line after if
else
success = false;
Nested ifs
Another issue with ifs is that we can nest them, put then inside of each other.
if( today == Day.Monday )
{
if( time < 12.00 )
{
// Code here runs if it before 12 on Monday
}
else
{
// Code here runs if is after 12 on Monday
}
}
These nested if's can be helpful for adding more branches and ways to go inside of our code. The only tricky thing to watch out for with the nesting is the else. The else must be set based on where it is in the parenthesis or it matches up with the previous if. For example:
if( test1 )
// Test 1 is true doe line
if( test 2 )
// Test 2 is true do line
else
// This line runs if test 2 is false, it doesn't have anything to do with test 1
Besides nesting another common thing to do with if statements is to put them in a series. Here's an example:
if( test1 )
...
else
if (test 2 )
{
// Code here runs if test 1 is false and test 2 is true.
}
We could keep adding these else-if's to the end of the if-statement. This is a good way to choose among several options. If we have too many of these, though; we might want to use a switch statement instead.
Switch Statement
A switch statement takes in a variable and then does different code based on the value of the variable. This is helpful when we have a series of tests based on a single variable. Here's an example:
static void Main(string[] args)
{
int number;
Console.Write("Enter a number between 1 and 5 : ");
number = Convert.ToInt32(Console.ReadLine());
switch (number)
{
case 1:
Console.WriteLine("One is a good number");
break;
case 2:
Console.WriteLine( "Two is second best" );
break;
case 3:
Console.WriteLine("Three is something");
break;
case 4:
case 5:
Console.WriteLine("Four and Five aren't bad");
break;
default:
Console.WriteLine("You didn't enter a number from 1-5");
break;
}
}
The switch statement works by stating a variable in parenthesis after the switch:
switch( number )
Then following this it decides which code to execute based on its value. In the brackets after the switch we have a number of cases. They take the format:
case value:
So for our int variable we use the case:
case 1:
// Code to execute if variable is the value 1
break; // Stop executing code
Each case in our number example is just a different value for the number, if the value is true the code after the : is executed until a break statement is hit. If we want to have two or more cases execute the same code we can just put two cases on top of each other, just like the case 4: and case 5: in our example. The special case of default: at the end is just what it says. If we went through the switch statement and never had a correct case we'll run the code after the default. The cases are just like multiple if's.
The switch statement isn’t used nearly as much as the if statement. It's usually reserved for special cases where if we have a whole bunch of different choices of code based on the value of just one variable. A use that will come up for it a lot is when we read a variable for a key being pressed at the keyboard, and we might do different code depending on all the different keys that could have been pressed.
This covers the two types of branching. Next we'll look at looping.
Looping
For Loop
Many times in programming we need to repeat a block of code several times. One of the ways to do this is a for loop. A for loop uses a counter variable. It starts by initializing the counter variable, performs an operation on the counter at each loop, and runs until the counter variable passes some condition (test). This might be easiest to see with an example, we'll add the following after the else statement above:
Console.Write( “Enter your age: “ );
int age = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the current year: ");
int year = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < 5; i++)
{
year++;
age++;
Console.WriteLine( "In the year " + year.ToString() + " you'll be " + age.ToString() + " years old." );
}
An example run of this program is:
Enter you
age: 105
Enter the
current year: 2009
In the
year 2010 you'll be 106
years old.
In the
year 2011 you'll be 107
years old.
In the
year 2012 you'll be 108
years old.
In the
year 2013 you'll be 109
years old.
In the
year 2014 you'll be 110
years old.
This addition prints out the user's age for the next five years. The for loop starts by creating the counter variable i and setting it to zero, and will continue to loop while i is less than five, and at each loop run it adds one to i.
Notice that it is common in programming to count using zero based indexing which means instead of starting counting at 1, such as 1,2,3.. we start at zero 0,1,2 ... If we had three objects, the first would be numbered 0, the second would be numbered 1, and the third would be number 3. So to count to five we start with i = 0 and it counts 0,1,2,3,4 – which is five loops total. This starting at zero can take a little getting used too, but it's good to get into the habit of counting this way since when we get to arrays we'll see you'll have to use zero-based indexing.
We see that the for loop uses the counter variable and consists of three parts.
In the first part we initialize the counter variable, usually just setting it to zero, as in our int i = 0;
In the second part we define an exit condition for the for loop. Exit conditions are important in looping, an ext condition is just a way to make sure the loop stops at some point and doesn't repeat forever. The exit condition is a statement that says the loop is over. Usually with for loops our exit condition is just testing if our counter variable has gone up to a certain number.
The third part we perform an operation on the counter variable. This is usually just adding one to the counter. The syntax for these three things is:
for( counter variable initialization; counter variable test; counter variable operation )
Note the placement of the semicolons, its important to have them in the proper places for them to work correctly.
Multiple for loops
We can have multiple for loops together, this can be helpful as we go through multiple things at once. Here's a little example that will print out a little 10 by 10 grid of numbers.
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
Console.Write(j.ToString());
Console.Write("\n");
}
}
The output or this program is:
0000000000
1111111111
2222222222
3333333333
4444444444
5555555555
6666666666
7777777777
8888888888
9999999999
For loops are very common and occur in every procedural language, such as C++ and Java, they are handy for running code a specific number of loops. But what if we don't know how many times we want the loop to run? The loop we can use instead of the for loop is the while loop.
while loop
A while loop is another loop type that is simpler than the for loop. All that is needed for a while loop is have a conditional, test, and while that test is true the while loop will keep executing. The basic format is simple:
while( test )
{
// Test is true, execute code here
} // End of while loop, go back up to test
Let's create a small example, a program that asks the user to guess a number, and then keeps asking (looping) for another guess until the user guess the correct number:
static void Main(string[] args)
{
int secretNumber = 3;
Console.WriteLine("Guess the number game, enter a number between 1
and 10: ");
int guess = Convert.ToInt32(Console.ReadLine());
while (guess != secretNumber)
{
Console.WriteLine("Wrong, guess again : ");
guess = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Correct!");
}
A sample run of this is:
Guess the
number game, enter a number between 1 and 10:
5
Wrong,
guess again:
3
Correct!
This program picks a secret number and will continue looping while the number inputted does not match it. (Remember != means not equal.) This program could loop 10 times 100 times, or a 1000 times (as long as three is not guessed.) The one thing to watch out for is that the loops have an exit condition, a guarantee that the loop will not run forever. If we wrote a loop that had no way of exiting, such as:
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("We're looping forever ");
}
}
It will never end. When this happens in the best cases this just hangs up the program. In others it causes everything to crash. We always want some way to exit. Besides just the initial test condition, there are two other ways that we can control how the loop runs, the break and continue statement. Both only work inside of loops, and work for for's and while's. The continue statement says to ignore everything below it in the run of the loop, and go back to the beginning. For instance, look at the following code:
int test = 0;
while( test < 10 )
{
if( test == 5 )
continue;
Console.WriteLine( test.ToString() );
test++;
}
The output for this is:
012346789
The above program (which is similar in it's working as a for loop) prints out the numbers 0 to 9, with the exception of 5. The if test is equal to 5 the break happens and the rest of the loop is skipped and the loop goes back to the beginning.
The break statement simply exits the loop directly. The following loop will print out the numbers 0-9, though the test on the while loop is always true the loop will exit when the test number goes above 9:
int test = 0;
while( true)
{
if( test > 9 )
break;
Console.WriteLine( test.ToString() );
test++;
}
The output is simply:
012345678
When test is over 9 the break statement is called and the loop exits.
do-while
Let's go back a little bit to our secret number guessing game.
int guess = Convert.ToInt32(Console.ReadLine());
while (guess != secretNumber)
{
Console.WriteLine("Wrong, guess again : ");
guess = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Correct!");
In this program if the user enters the correct number the test for the while loop (guess != secretNumber) evaluates to false on the first try, and all of the code inside the while loop is skipped. Let's say we wanted the code inside a while loop to execute at least once, no matter what. For this we use a do-while loop, it always executes at least once because the test comes at the end of the loop. For example let's look at a different (and worse) way we could have written the guessing number program.
static void Main(string[] args)
{
int secretNumber = 3;
Console.WriteLine("Guess the number game");
int guess;
do
{
Console.WriteLine("Enter a number between 1 and 10: ");
guess = Convert.ToInt32(Console.ReadLine());
} while( guess != secretNumber );
Console.WriteLine("Correct!");
}
A sample run of this is:
Guess the
number game
Enter a
number between 1 and 10:
5
Enter a
number between 1 and 10:
3
Correct!
This program also keeps looping until the correct number is guessed, and the loop will be entered at least once.
Goto statement
Just a little note, there is one more kind of branching that we can do, and that is the use of the goto statement. The goto is an older method to jump around code, you mark different points of the program and then use goto to jump around to those points. We won't cover it here as we really shouldn't be using this, it quickly creates “spaghetti code,” code that jumps around a lot and is mostly unreadable.
Finding the Gold
When we left our “Finding the Gold” game we had put in the functionality to let the player enter their name and choose a door:
Console.WriteLine("Welcome to the Find the Gold Game!\n What is your
name?");
string name = Console.ReadLine();
Console.WriteLine("Hello, " + name + ". Which door do you choose, 1, 2, or
3?");
int door = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("You chose door " + door.ToString());
Now let's add in three choices. If the player chooses door 1 we'll let the player then choose to open box one or two. If the player chooses one we'll tell them it's empty, if they choose door two we'll tell them they found a bag of gold. So after the above add the following:
if( door == 1 )
{
Console.WriteLine(“You found two boxes, which do you choose?”);
int box = Convert.ToInt32(Console.ReadLine());
if( box == 1 )
Console.WriteLine(“It's empty. You lose!”);
if( box == 2 )
Console.WriteLine(“You found a bag of gold!”);
}
The output of this part of the program is:
You choose door 1
You found two boxes, which do you choose?
2
You found a bag of gold!
Next we'll have it if the player chooses door two we'll assume they fell into a hole. We'll print “you're falling” five times:
if( door == 2 )
{
for( int i = 0; i < 5; i++ )
Console.WriteLine(“You're falling!”);
}
The output of this part of the program is:
You choose door 2
You're falling!
You're falling!
You're falling!
You're falling!
You're falling!
As an option for door three you could tell the player the gold is in a safe have them need to undo a combination to get to it. Then you could insert the guessing game code to have them guess a number to find the gold.
Summary
Now we are getting closer to be able to do really interesting things in code. We looked at branching using the if-else and case statements, and how to create loops with the for loop and the different whiles. In the next chapter we'll look at some more advanced data types and how to divide up code with functions.
