On this page24 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. What Is a Loop?
- 2. Your First for Loop
- 3. The Three Parts
- 4. Tracing a Loop Step by Step
- 5. < or <=?
- 6. Counting Down
- 7. Counting in Steps
- 8. Adding Up a Total
- 9. Looping Over a String
- 10. The Counter Lives Inside the Loop
- 11. A Loop Inside a Loop
- 12. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 26 — for Loops
| Category | 5 — Control Flow |
| Lecture | 026 of 140 |
| Estimated video length | 12 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
Printing the numbers 1 to 100 so far means writing 100
forloop 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
lengthand reading one character withword[index](Lecture 008) - compound assignment (
+=,-=) and the remainder operator%(Lecture 017) - comparison operators such as
<and<=(Lecture 018) ++and--(Lecture 020)ifandif-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:
print(5 * 1);
print(5 * 2);
print(5 * 3);
// ... and seven more linesThe 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
forloop 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
Stringby its index - Write a simple loop inside another loop
- Recognize the errors caused by common
forloop 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
void main() {
for (var i = 1; i <= 3; i++) {
print('Hello, Ali!');
}
}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:
for (start; condition; update) {
body
}| Part | In our loop | Meaning |
|---|---|---|
| start | var i = 1 | create the counter; runs once, before anything else |
| condition | i <= 3 | checked before every iteration; false ends the loop |
| update | i++ | runs after every iteration |
The counter is usually called i (short for index). It is a normal variable, so the body can
print it:
void main() {
for (var i = 1; i <= 5; i++) {
print(i);
}
}1
2
3
4
54. Tracing a Loop Step by Step
Dart always follows the same order: start → check → body → update → check → body → …
void main() {
for (var i = 1; i <= 3; i++) {
print('Lap $i');
}
print('Done');
}Lap 1
Lap 2
Lap 3
Done| Step | i | i <= 3? | What happens |
|---|---|---|---|
| start | 1 | — | i is created |
| 1 | 1 | true | print Lap 1, then i++ |
| 2 | 2 | true | print Lap 2, then i++ |
| 3 | 3 | true | print Lap 3, then i++ |
| 4 | 4 | false | loop 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:
void main() {
for (var i = 0; i < 5; i++) {
print('Run ${i + 1}');
}
}Run 1
Run 2
Run 3
Run 4
Run 5Starting 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 --:
void main() {
for (var i = 5; i >= 1; i--) {
print(i);
}
print('Lift off!');
}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:
void main() {
for (var i = 0; i <= 10; i += 2) {
print(i);
}
}0
2
4
6
8
10void main() {
for (var minutes = 0; minutes <= 30; minutes += 10) {
print('$minutes min');
}
}0 min
10 min
20 min
30 minThe 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.
void main() {
var total = 0;
for (var i = 1; i <= 5; i++) {
total += i;
}
print('Total: $total');
}Total: 15total 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:
void main() {
var evens = 0;
for (var i = 1; i <= 10; i++) {
if (i % 2 == 0) {
evens++;
}
}
print('Even numbers: $evens');
}Even numbers: 59. 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:
void main() {
var name = 'Sara';
for (var i = 0; i < name.length; i++) {
print('Index $i: ${name[i]}');
}
}Index 0: S
Index 1: a
Index 2: r
Index 3: ai < name.length is the safe condition: it works for any string, of any length. Combine it
with if to count matching characters:
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.');
}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:
void main() {
for (var i = 1; i <= 3; i++) {
print(i);
}
print(i); // ✗
}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:
void main() {
for (var row = 1; row <= 3; row++) {
var line = '';
for (var col = 1; col <= row; col++) {
line += '* ';
}
print(line);
}
}*
* *
* * * 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:
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');
}Month 1: 500
Month 2: 1000
Month 3: 2500
Month 4: 3000
Month 5: 3500
Month 6: 4000
Saved after 6 months: 4000The 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
void main() {
for (var i = 1; i <= 5; i++) {
print('Number $i');
}
}Number 1
Number 2
Number 3
Number 4
Number 5Example 2 — Counting Down
void main() {
for (var i = 3; i >= 1; i--) {
print('$i...');
}
print('Go!');
}3...
2...
1...
Go!Example 3 — Odd Numbers in Steps of 2
void main() {
for (var i = 1; i < 10; i += 2) {
print(i);
}
}1
3
5
7
9Example 4 — The 5-Times Table
void main() {
for (var i = 1; i <= 10; i++) {
print('5 x $i = ${5 * i}');
}
}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 = 50Example 5 — Spelling a Word
void main() {
var word = 'Dart';
for (var i = 0; i < word.length; i++) {
print(word[i]);
}
}D
a
r
tExample 6 — Reversing a String
void main() {
var word = 'Zayan';
var reversed = '';
for (var i = word.length - 1; i >= 0; i--) {
reversed += word[i];
}
print(reversed);
}nayaZHow it works
- The counter starts at the last index,
word.length - 1, which is4. i >= 0keeps going down to index0, the first character.- Each character is added to the end of
reversed.
Example 7 — Student Marks Total
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}');
}After subject 1: 80
After subject 2: 160
After subject 3: 240
After subject 4: 320
Average: 80.0Example 8 — Shopping Price List
void main() {
var price = 250;
for (var quantity = 1; quantity <= 4; quantity++) {
print('$quantity x notebook = ${price * quantity}');
}
}1 x notebook = 250
2 x notebook = 500
3 x notebook = 750
4 x notebook = 1000Example 9 — Bank Balance with Interest
void main() {
var balance = 1000.0;
for (var year = 1; year <= 3; year++) {
balance += balance * 0.1;
print('Year $year: ${balance.toStringAsFixed(2)}');
}
}Year 1: 1100.00
Year 2: 1210.00
Year 3: 1331.00How it works
balanceis adouble, declared before the loop so it keeps growing.- Each year adds 10% of the current balance, so the interest grows too.
toStringAsFixed(2)(Lecture 009) formats the money for display.
Example 10 — Temperature Conversion Table
void main() {
for (var celsius = 0; celsius <= 40; celsius += 10) {
var fahrenheit = celsius * 9 / 5 + 32;
print('$celsius °C = $fahrenheit °F');
}
}0 °C = 32.0 °F
10 °C = 50.0 °F
20 °C = 68.0 °F
30 °C = 86.0 °F
40 °C = 104.0 °FCommon Beginner Mistakes
1. Commas instead of semicolons
void main() {
// for (var i = 1; i <= 3, i++) { // ✗
// print(i);
// }
}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
void main() {
for (var i = 1; i <= 3; i++) {
print(i);
}
// print(i); // ✗
}Error: Undefined name 'i'.Store anything you need later in a variable declared before the loop.
3. Going one index too far
void main() {
var word = 'Dart';
// for (var i = 0; i <= word.length; i++) { // ✗ should be <
// print(word[i]);
// }
}D
a
r
t
Unhandled exception:
RangeError (index): Invalid value: Not in inclusive range 0..3: 4This 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
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
void main() {
for (var i = 1; i <= 3; i++) ; // ✗ the ; is an empty body
{
print('Hello');
}
}HelloNo 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
void main() {
for (var i = 1; i <= 3; i++) {
var total = 0; // ✗ reset on every iteration
total += i;
print(total);
}
}1
2
3total 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:
10
8
6
4
2
0
Sale is open!Try it yourself before opening the solution.
Show solution
void main() {
for (var i = 10; i >= 0; i -= 2) {
print(i);
}
print('Sale is open!');
}10
8
6
4
2
0
Sale is open!How it works
- The counter starts at
10and the updatei -= 2moves it down by two. i >= 0includes0;i > 0would stop at2.
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
- Print the numbers
1to7, each on its own line. - Print
Dart is fun!exactly 4 times. - Print the numbers from
10down to6.
Application
-
Print the multiples of 5 from
5to25using+= 5. -
Add up the numbers
1to10and printSum: 55. -
Print each character of
'Ali'with its index, as0: A,1: l,2: i. -
Count how many numbers from
1to20are divisible by 3, and printCount: 6. -
How many times does this loop print? Answer first, then run it to check:
void main() { for (var i = 2; i < 11; i += 3) { print(i); } }
Challenge
-
Count the vowels (
a,e,i,o,u) in'education'and printVowels: 5. -
Use nested loops to print this pattern:
1 1 2 1 2 3 1 2 3 4
Practice Answers
Question 1 — Solution
void main() {
for (var i = 1; i <= 7; i++) {
print(i);
}
}1
2
3
4
5
6
7Question 2 — Solution
void main() {
for (var i = 0; i < 4; i++) {
print('Dart is fun!');
}
}Dart is fun!
Dart is fun!
Dart is fun!
Dart is fun!Question 3 — Solution
void main() {
for (var i = 10; i >= 6; i--) {
print(i);
}
}10
9
8
7
6Question 4 — Solution
void main() {
for (var i = 5; i <= 25; i += 5) {
print(i);
}
}5
10
15
20
25Question 5 — Solution
void main() {
var sum = 0;
for (var i = 1; i <= 10; i++) {
sum += i;
}
print('Sum: $sum');
}Sum: 55Question 6 — Solution
void main() {
var name = 'Ali';
for (var i = 0; i < name.length; i++) {
print('$i: ${name[i]}');
}
}0: A
1: l
2: iQuestion 7 — Solution
void main() {
var count = 0;
for (var i = 1; i <= 20; i++) {
if (i % 3 == 0) {
count++;
}
}
print('Count: $count');
}Count: 6Question 8 — Solution
It prints 3 times: i takes the values 2, 5, 8. The next value, 11, fails i < 11.
2
5
8Question 9 — Solution
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');
}Vowels: 5Question 10 — Solution
void main() {
for (var row = 1; row <= 4; row++) {
var line = '';
for (var n = 1; n <= row; n++) {
line += '$n ';
}
print(line.trim());
}
}1
1 2
1 2 3
1 2 3 4trim() (Lecture 008) removes the extra space after the last number.
Quick Revision
- What are the three parts of a
forloop, and what separates them? - How many times does the start part run? And the condition?
- How many times does
for (var i = 0; i < 5; i++)run? - Which three parts change when you count down instead of up?
- Why must a total be declared before the loop?
- Which condition safely visits every index of a string?
- Can you use the counter
iafter 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.
1to<= nand0to< nboth runntimes — 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.lengthvisits 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.