Computers are good at doing the same thing over and over without getting bored. Instead of writing a statement out a hundred times, you write a loop: a block that is repeated until a condition no longer holds.
while: as long as something holds
// countdown.cs
int number = 5;
while (number > 0)
{
Console.WriteLine(number);
number = number - 1;
}
Console.WriteLine("Liftoff!");
5
4
3
2
1
Liftoff!
Before every round, while checks the condition. If it is true, the block runs, and then the condition is checked again. If it is
false, the program goes on after the block. Inside the block, number gets one smaller each time, until the condition number > 0
no longer holds.
For “one smaller” and similar calculations, there are shorthand forms you will see often:
| Shorthand | Written out |
|---|---|
number--; |
number = number - 1; |
number++; |
number = number + 1; |
sum += 5; |
sum = sum + 5; |
When a loop doesn’t stop
As a test, delete the line number = number - 1; in countdown.cs and run the program. Now number stays 5, the condition stays
true, and the program writes 5 on line after line, forever. That’s an infinite loop. Nothing to worry about: press Ctrl+C in
the terminal. That stops any running program, on Windows, macOS and Linux alike (on a Mac, too, it’s the Control key, not Command).
Then put the line back.
For every loop, ask yourself: what in the block makes sure the condition turns false at some point?
for: counting
Very often, a loop simply counts from one number to another. That’s what for is made for:
// times-table.cs
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"{i} x 7 = {i * 7}");
}
1 x 7 = 7
2 x 7 = 14
3 x 7 = 21
4 x 7 = 28
5 x 7 = 35
6 x 7 = 42
7 x 7 = 49
8 x 7 = 56
9 x 7 = 63
10 x 7 = 70
The parentheses after for hold three parts, separated by semicolons:
int i = 1runs once at the start and creates the counter.i <= 10is checked before every round, just like withwhile.i++runs after every round and counts on.
The name i is the usual one for counters. But you can also call it row or number.
Collecting values
A loop can collect results across all its rounds. To do that, you create a variable before the loop and change it in every round:
// sum.cs
int sum = 0;
for (int i = 1; i <= 100; i++)
{
sum += i;
}
Console.WriteLine($"The sum of 1 to 100 is {sum}.");
The sum of 1 to 100 is 5050.
If int sum = 0; were inside the block, the sum would start over at 0 in every round, and after the block it wouldn’t exist at all.
The compiler would reject the last line. A variable only lives in the block where it was created.
Input until someone stops
Often a program doesn’t know in advance how much input will come. Then a loop runs “forever,” with while (true), and is left from
the inside with break as soon as a certain input comes, here an empty line:
// add-numbers.cs
int sum = 0;
int count = 0;
Console.WriteLine("Enter whole numbers. An empty line ends the input.");
while (true)
{
Console.Write("Number: ");
string input = Console.ReadLine() ?? "";
if (input == "")
{
break;
}
if (int.TryParse(input, out int number))
{
sum += number;
count++;
}
else
{
Console.WriteLine("That was not a whole number, I'll skip it.");
}
}
Console.WriteLine($"{count} numbers, sum {sum}.");
Enter whole numbers. An empty line ends the input.
Number: 12
Number: 30
Number: two
That was not a whole number, I'll skip it.
Number: 8
Number:
3 numbers, sum 50.
break ends the loop right away, and the program goes on after it. Because Console.ReadLine() ?? "" gives an empty text when the
input has ended, the loop also ends cleanly when no more input comes at all.
Exercise 1
Write ten-to-zero.cs. Using a for loop, it should print the numbers 10, 8, 6, 4, 2, 0, each on its own line. Tip: the third part
in the parentheses can count differently from i++.
Solution 1
// ten-to-zero.cs
for (int i = 10; i >= 0; i -= 2)
{
Console.WriteLine(i);
}
10
8
6
4
2
0
The counter starts at 10, gets 2 smaller after every round (i -= 2), and the loop runs as long as it is at least 0. Had you written
i > 0, the 0 at the end would be missing. Here, too, it pays to look at the boundary.
Exercise 2
Write the game guess-the-number.cs. The program knows a secret number between 1 and 100, 42 to start with. You guess. After every
guess, the program says “too low,” “too high” or “correct.” At the end, it tells you how many tries you needed. An empty input ends the
game early. Input that isn’t a number doesn’t count as a try.
Solution 2
// guess-the-number.cs
int secret = 42;
int tries = 0;
Console.WriteLine("I'm thinking of a number between 1 and 100.");
while (true)
{
Console.Write("Your guess: ");
string input = Console.ReadLine() ?? "";
if (input == "")
{
Console.WriteLine($"Too bad. The number was {secret}.");
break;
}
if (!int.TryParse(input, out int guess))
{
Console.WriteLine("Please enter a whole number.");
continue;
}
tries++;
if (guess < secret)
{
Console.WriteLine("Too low.");
}
else if (guess > secret)
{
Console.WriteLine("Too high.");
}
else
{
Console.WriteLine($"Correct! Number of tries: {tries}");
break;
}
}
I'm thinking of a number between 1 and 100.
Your guess: 50
Too high.
Your guess: 25
Too low.
Your guess: 37
Too low.
Your guess: 43
Too high.
Your guess: 42
Correct! Number of tries: 5
What’s new here is continue: it jumps straight to the next round without running the rest of the block. That way, wrong input doesn’t
count as a try.
With a fixed 42, the game is only exciting once. Replace the line int secret = 42; with
int secret = Random.Shared.Next(1, 101);. Then the program comes up with a new number from 1 to 100 every time it starts. The upper
limit, 101, is itself no longer included.
If you guess cleverly, you cut the range in half with every guess, as in the example above. That way, you never need more than seven tries.
Exercise 3
Write stairs.cs, which prints these stairs made of stars:
*
**
***
****
*****
Tip: you need two loops, one for the rows and, inside it, one for the stars of a row. Console.Write("*") writes a star without
ending the line.
Solution 3
// stairs.cs
for (int row = 1; row <= 5; row++)
{
for (int star = 1; star <= row; star++)
{
Console.Write("*");
}
Console.WriteLine();
}
The outer loop counts the rows. The inner one writes as many stars in each row as the row’s number: one in row 1, five in row 5. Then
Console.WriteLine() ends the line. Change the 5 to a 10 and watch the stairs grow.
What you can do now
- You repeat statements with
whileas long as a condition holds. - You count with
forand choose the start, the end and the step yourself. - You leave a loop with
break, skip a round withcontinueand stop a stuck program with Ctrl+C. - You collect values in a variable created before the loop.
- You put one loop inside another.
Read more
- Branches and loops: loops in Microsoft’s
tutorial series, including the
doloop and nested loops. - Iterate through a code block using for statement in C#: a module with
exercises on
for. - Add looping logic to your code using the do-while and while statements in C#:
a module on
whileanddo.