Watch the video (12 min)
On this page24 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. What Is a Loop?
  5. 2. Your First for Loop
  6. 3. The Three Parts
  7. 4. Tracing a Loop Step by Step
  8. 5. < or <=?
  9. 6. Counting Down
  10. 7. Counting in Steps
  11. 8. Adding Up a Total
  12. 9. Looping Over a String
  13. 10. The Counter Lives Inside the Loop
  14. 11. A Loop Inside a Loop
  15. 12. A Real-World Example
  16. Code Examples
  17. Common Beginner Mistakes
  18. Best Practices
  19. Mini Challenge
  20. Practice Questions
  21. Practice Answers
  22. Quick Revision
  23. Key Takeaways
  24. What's Next?

Lecture 26 — for Loops

Category5 — Control Flow
Lecture026 of 140
Estimated video length12 min
TargetDart 3.12.2
LevelBeginner

Printing the numbers 1 to 100 so far means writing 100 print lines. A for loop writes the instruction once and tells Dart how many times to repeat it.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 001–025:

  • variables with var, and string interpolation with $ and ${...}
  • string length and reading one character with word[index] (Lecture 008)
  • compound assignment (+=, -=) and the remainder operator % (Lecture 017)
  • comparison operators such as < and <= (Lecture 018)
  • ++ and -- (Lecture 020)
  • if and if-else (Lectures 022–023)

Connection With Previous Lectures

Since Lecture 022, a condition decides whether a block of code runs. But every block still runs at most once. To print a 5-times table, we would write:

dart
print(5 * 1);
print(5 * 2);
print(5 * 3);
// ... and seven more lines

The ten lines are identical except for one number that goes up by one each time. In Lecture 020 we learned ++ for exactly that kind of counting — but we had nowhere to use it. A program needs a way to say "repeat this block, and count while you do it".


Learning Objectives

By the end of this lecture you will be able to:

  • Explain what a loop is and why programs need one
  • Write a for loop with its three parts: start, condition, and update
  • Trace a loop step by step and predict its output
  • Count up, count down, and count in steps of more than one
  • Add values up in a total while a loop runs
  • Visit every character of a String by its index
  • Write a simple loop inside another loop
  • Recognize the errors caused by common for loop mistakes

1. What Is a Loop?

A loop runs the same block of code again and again, as long as a condition stays true. Each single run of the block is called an iteration.

Analogy — think of a runner doing laps of a track. Before each lap, the coach checks the lap counter: "fewer than 4 laps? Run another." After each lap, the counter goes up by one. When the answer is "no", the runner stops.

A for loop is exactly that: a counter, a question, and a step.


2. Your First for Loop

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    print('Hello, Ali!');
  }
}
output
Hello, Ali!
Hello, Ali!
Hello, Ali!

One print, three lines of output. The block between { and } is called the body of the loop. Changing 3 to 100 would print the greeting 100 times — no extra code needed.


3. The Three Parts

Inside the brackets are three parts, separated by semicolons:

output
for (start; condition; update) {
  body
}
PartIn our loopMeaning
startvar i = 1create the counter; runs once, before anything else
conditioni <= 3checked before every iteration; false ends the loop
updatei++runs after every iteration

The counter is usually called i (short for index). It is a normal variable, so the body can print it:

dart
void main() {
  for (var i = 1; i <= 5; i++) {
    print(i);
  }
}
output
1
2
3
4
5

4. Tracing a Loop Step by Step

Dart always follows the same order: start → check → body → update → check → body → …

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    print('Lap $i');
  }
  print('Done');
}
output
Lap 1
Lap 2
Lap 3
Done
Stepii <= 3?What happens
start1—i is created
11trueprint Lap 1, then i++
22trueprint Lap 2, then i++
33trueprint Lap 3, then i++
44falseloop ends; Done is printed

Notice that i reaches 4 — the check fails after the last update. The body never sees that 4.


5. < or <=?

The condition decides exactly where counting stops. i < 5 stops before 5; i <= 5 includes it:

dart
void main() {
  for (var i = 0; i < 5; i++) {
    print('Run ${i + 1}');
  }
}
output
Run 1
Run 2
Run 3
Run 4
Run 5

Starting at 0 with i < 5 also runs 5 times — the counter takes the values 0, 1, 2, 3, 4. Both styles are common: 1 to <= n reads naturally for counting, while 0 to < n matches indexes, as we will see in section 9. Running one time too many or too few is called an off-by-one error — always check the first and last value.


6. Counting Down

To count backwards, start high, keep going while the counter is above the end, and use --:

dart
void main() {
  for (var i = 5; i >= 1; i--) {
    print(i);
  }
  print('Lift off!');
}
output
5
4
3
2
1
Lift off!

All three parts changed together: start at 5, check i >= 1, update with i--.


7. Counting in Steps

The update does not have to be ++. Any change works — for example += 2 or += 10:

dart
void main() {
  for (var i = 0; i <= 10; i += 2) {
    print(i);
  }
}
output
0
2
4
6
8
10
dart
void main() {
  for (var minutes = 0; minutes <= 30; minutes += 10) {
    print('$minutes min');
  }
}
output
0 min
10 min
20 min
30 min

The counter can have any name. minutes says more than i when the value means something.


8. Adding Up a Total

A very common pattern: create a variable before the loop, and add to it inside the loop.

dart
void main() {
  var total = 0;
  for (var i = 1; i <= 5; i++) {
    total += i;
  }
  print('Total: $total');
}
output
Total: 15

total grows 1, 3, 6, 10, 15. It must be declared outside the loop — a variable declared inside the body is created fresh on every iteration, and the sum would be lost. The same idea works with *, or with if to decide what to count:

dart
void main() {
  var evens = 0;
  for (var i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
      evens++;
    }
  }
  print('Even numbers: $evens');
}
output
Even numbers: 5

9. Looping Over a String

In Lecture 008, you read one character with word[0]. A loop can read every character, because its indexes run from 0 to length - 1:

dart
void main() {
  var name = 'Sara';
  for (var i = 0; i < name.length; i++) {
    print('Index $i: ${name[i]}');
  }
}
output
Index 0: S
Index 1: a
Index 2: r
Index 3: a

i < name.length is the safe condition: it works for any string, of any length. Combine it with if to count matching characters:

dart
void main() {
  var word = 'banana';
  var count = 0;
  for (var i = 0; i < word.length; i++) {
    if (word[i] == 'a') {
      count++;
    }
  }
  print('The letter a appears $count times.');
}
output
The letter a appears 3 times.

When you need only the characters and not their positions, the for-in loop in the next lecture is shorter.


10. The Counter Lives Inside the Loop

A counter created in the start part exists only inside the loop. Using it afterwards is an error:

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    print(i);
  }
  print(i); // ✗
}
output
Error: Undefined name 'i'.
  print(i); // ✗
        ^

If you need a value after the loop, store it in a variable declared before the loop, like total in section 8. This also means two loops in a row can both use the name i.


11. A Loop Inside a Loop

The body of a loop can contain another loop. The inner loop runs completely for every single iteration of the outer loop:

dart
void main() {
  for (var row = 1; row <= 3; row++) {
    var line = '';
    for (var col = 1; col <= row; col++) {
      line += '* ';
    }
    print(line);
  }
}
output
* 
* * 
* * * 

On row 1 the inner loop runs once, on row 2 twice, on row 3 three times. Nested loops multiply the work quickly — 100 rows of 100 columns is 10,000 iterations — so use them only when the problem really has rows and columns.


12. A Real-World Example

Ali saves 500 every month for 6 months. In month 3 his uncle adds a bonus of 1000. Print his balance at the end of each month, and the total at the end:

dart
void main() {
  var balance = 0;
  var monthly = 500;
  for (var month = 1; month <= 6; month++) {
    balance += monthly;
    if (month == 3) {
      balance += 1000;
    }
    print('Month $month: $balance');
  }
  print('Saved after 6 months: $balance');
}
output
Month 1: 500
Month 2: 1000
Month 3: 2500
Month 4: 3000
Month 5: 3500
Month 6: 4000
Saved after 6 months: 4000

The counter month drives the loop, balance accumulates outside it, and an if inside the body handles the one special month. Changing 6 to 12 plans a whole year.


Code Examples

Example 1 — Counting 1 to 5

dart
void main() {
  for (var i = 1; i <= 5; i++) {
    print('Number $i');
  }
}
output
Number 1
Number 2
Number 3
Number 4
Number 5

Example 2 — Counting Down

dart
void main() {
  for (var i = 3; i >= 1; i--) {
    print('$i...');
  }
  print('Go!');
}
output
3...
2...
1...
Go!

Example 3 — Odd Numbers in Steps of 2

dart
void main() {
  for (var i = 1; i < 10; i += 2) {
    print(i);
  }
}
output
1
3
5
7
9

Example 4 — The 5-Times Table

dart
void main() {
  for (var i = 1; i <= 10; i++) {
    print('5 x $i = ${5 * i}');
  }
}
output
5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50

Example 5 — Spelling a Word

dart
void main() {
  var word = 'Dart';
  for (var i = 0; i < word.length; i++) {
    print(word[i]);
  }
}
output
D
a
r
t

Example 6 — Reversing a String

dart
void main() {
  var word = 'Zayan';
  var reversed = '';
  for (var i = word.length - 1; i >= 0; i--) {
    reversed += word[i];
  }
  print(reversed);
}
output
nayaZ

How it works

  1. The counter starts at the last index, word.length - 1, which is 4.
  2. i >= 0 keeps going down to index 0, the first character.
  3. Each character is added to the end of reversed.

Example 7 — Student Marks Total

dart
void main() {
  var subjects = 4;
  var markPerSubject = 80;
  var total = 0;
  for (var i = 1; i <= subjects; i++) {
    total += markPerSubject;
    print('After subject $i: $total');
  }
  print('Average: ${total / subjects}');
}
output
After subject 1: 80
After subject 2: 160
After subject 3: 240
After subject 4: 320
Average: 80.0

Example 8 — Shopping Price List

dart
void main() {
  var price = 250;
  for (var quantity = 1; quantity <= 4; quantity++) {
    print('$quantity x notebook = ${price * quantity}');
  }
}
output
1 x notebook = 250
2 x notebook = 500
3 x notebook = 750
4 x notebook = 1000

Example 9 — Bank Balance with Interest

dart
void main() {
  var balance = 1000.0;
  for (var year = 1; year <= 3; year++) {
    balance += balance * 0.1;
    print('Year $year: ${balance.toStringAsFixed(2)}');
  }
}
output
Year 1: 1100.00
Year 2: 1210.00
Year 3: 1331.00

How it works

  1. balance is a double, declared before the loop so it keeps growing.
  2. Each year adds 10% of the current balance, so the interest grows too.
  3. toStringAsFixed(2) (Lecture 009) formats the money for display.

Example 10 — Temperature Conversion Table

dart
void main() {
  for (var celsius = 0; celsius <= 40; celsius += 10) {
    var fahrenheit = celsius * 9 / 5 + 32;
    print('$celsius °C = $fahrenheit °F');
  }
}
output
0 °C = 32.0 °F
10 °C = 50.0 °F
20 °C = 68.0 °F
30 °C = 86.0 °F
40 °C = 104.0 °F

Common Beginner Mistakes

1. Commas instead of semicolons

dart
void main() {
  // for (var i = 1; i <= 3, i++) { // ✗
  //   print(i);
  // }
}
output
Error: Expected ';' after this.
  for (var i = 1; i <= 3, i++) {
                       ^
Error: Expected an identifier, but got ','.

The three parts are always separated by semicolons.

2. Using the counter after the loop

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    print(i);
  }
  // print(i); // ✗
}
output
Error: Undefined name 'i'.

Store anything you need later in a variable declared before the loop.

3. Going one index too far

dart
void main() {
  var word = 'Dart';
  // for (var i = 0; i <= word.length; i++) { // ✗ should be <
  //   print(word[i]);
  // }
}
output
D
a
r
t
Unhandled exception:
RangeError (index): Invalid value: Not in inclusive range 0..3: 4

This one compiles and runs — then crashes. 'Dart' has indexes 0..3, but <= lets i reach 4. Use i < word.length.

4. Updating in the wrong direction

dart
void main() {
  // for (var i = 1; i <= 5; i--) { // ✗ never stops
  //   print(i);
  // }
}

i goes 1, 0, -1, -2, … and is always <= 5, so the loop never ends — an infinite loop. If it happens, stop the program with Ctrl + C in the terminal. Make sure the update moves the counter toward the end of the condition.

5. A semicolon after the brackets

dart
void main() {
  for (var i = 1; i <= 3; i++) ; // ✗ the ; is an empty body
  {
    print('Hello');
  }
}
output
Hello

No error at all — which is the problem. The ; ends the loop with an empty body, so the loop runs three times doing nothing, and the block below runs once. Never put ; after the for (...).

6. Declaring the total inside the loop

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    var total = 0; // ✗ reset on every iteration
    total += i;
    print(total);
  }
}
output
1
2
3

total starts again at 0 each time. Move it above the loop.


Best Practices

  • Use i < text.length (not <=) when looping over indexes.
  • Check the first and last value of every loop to avoid off-by-one errors.
  • Make sure the update moves the counter toward the end of the condition.
  • Give the counter a meaningful name (month, year, row) when it means something.
  • Declare totals and results before the loop.
  • Don't change the counter inside the body — let the update part do it.
  • Keep nested loops to two levels, and only for rows-and-columns problems.

Mini Challenge

Sara wants a countdown for her shop's sale that counts from 10 down to 0 in steps of 2, then announces the sale.

Your program should print exactly:

output
10
8
6
4
2
0
Sale is open!

Try it yourself before opening the solution.

Show solution
dart
void main() {
  for (var i = 10; i >= 0; i -= 2) {
    print(i);
  }
  print('Sale is open!');
}
output
10
8
6
4
2
0
Sale is open!

How it works

  1. The counter starts at 10 and the update i -= 2 moves it down by two.
  2. i >= 0 includes 0; i > 0 would stop at 2.

Practice Questions

Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.

Beginner

  1. Print the numbers 1 to 7, each on its own line.
  2. Print Dart is fun! exactly 4 times.
  3. Print the numbers from 10 down to 6.

Application

  1. Print the multiples of 5 from 5 to 25 using += 5.

  2. Add up the numbers 1 to 10 and print Sum: 55.

  3. Print each character of 'Ali' with its index, as 0: A, 1: l, 2: i.

  4. Count how many numbers from 1 to 20 are divisible by 3, and print Count: 6.

  5. How many times does this loop print? Answer first, then run it to check:

    dart
    void main() {
      for (var i = 2; i < 11; i += 3) {
        print(i);
      }
    }

Challenge

  1. Count the vowels (a, e, i, o, u) in 'education' and print Vowels: 5.

  2. Use nested loops to print this pattern:

    output
    1
    1 2
    1 2 3
    1 2 3 4

Practice Answers

Question 1 — Solution

dart
void main() {
  for (var i = 1; i <= 7; i++) {
    print(i);
  }
}
output
1
2
3
4
5
6
7

Question 2 — Solution

dart
void main() {
  for (var i = 0; i < 4; i++) {
    print('Dart is fun!');
  }
}
output
Dart is fun!
Dart is fun!
Dart is fun!
Dart is fun!

Question 3 — Solution

dart
void main() {
  for (var i = 10; i >= 6; i--) {
    print(i);
  }
}
output
10
9
8
7
6

Question 4 — Solution

dart
void main() {
  for (var i = 5; i <= 25; i += 5) {
    print(i);
  }
}
output
5
10
15
20
25

Question 5 — Solution

dart
void main() {
  var sum = 0;
  for (var i = 1; i <= 10; i++) {
    sum += i;
  }
  print('Sum: $sum');
}
output
Sum: 55

Question 6 — Solution

dart
void main() {
  var name = 'Ali';
  for (var i = 0; i < name.length; i++) {
    print('$i: ${name[i]}');
  }
}
output
0: A
1: l
2: i

Question 7 — Solution

dart
void main() {
  var count = 0;
  for (var i = 1; i <= 20; i++) {
    if (i % 3 == 0) {
      count++;
    }
  }
  print('Count: $count');
}
output
Count: 6

Question 8 — Solution

It prints 3 times: i takes the values 2, 5, 8. The next value, 11, fails i < 11.

output
2
5
8

Question 9 — Solution

dart
void main() {
  var word = 'education';
  var vowels = 0;
  for (var i = 0; i < word.length; i++) {
    var c = word[i];
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
      vowels++;
    }
  }
  print('Vowels: $vowels');
}
output
Vowels: 5

Question 10 — Solution

dart
void main() {
  for (var row = 1; row <= 4; row++) {
    var line = '';
    for (var n = 1; n <= row; n++) {
      line += '$n ';
    }
    print(line.trim());
  }
}
output
1
1 2
1 2 3
1 2 3 4

trim() (Lecture 008) removes the extra space after the last number.


Quick Revision

  1. What are the three parts of a for loop, and what separates them?
  2. How many times does the start part run? And the condition?
  3. How many times does for (var i = 0; i < 5; i++) run?
  4. Which three parts change when you count down instead of up?
  5. Why must a total be declared before the loop?
  6. Which condition safely visits every index of a string?
  7. Can you use the counter i after the loop ends?

Key Takeaways

  • A loop repeats a block; each run is an iteration.
  • for (start; condition; update) — parts separated by semicolons.
  • The start runs once; the condition is checked before every iteration; the update runs after.
  • 1 to <= n and 0 to < n both run n times — check first and last values.
  • Count down with -- and >=; count in steps with += or -=.
  • Declare totals before the loop and update them inside.
  • i < text.length visits every character of a string by index.
  • The counter exists only inside the loop.
  • An inner loop runs completely for each iteration of the outer loop.

What's Next?

Lecture 027 — for-in Loops. To visit every character in this lecture, we managed an index ourselves: start at 0, stop before length, add one each time. Often we don't care about the position — we just want each item in turn. The for-in loop hands you each item directly, with no counter to get wrong.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.