C++ Leap Year Checker Project
The deceptively tricky rules for whether a year has 366 days.
What you will build
One question — is this year a leap year? — with a rule that has two exceptions: divisible by 4, except centuries, unless divisible by 400. It's the perfect first exercise in translating a precise real-world rule into nested boolean logic without getting it wrong.
What you will learn
- The modulo operator
- Combining conditions with && and ||
- Operator precedence in boolean expressions
- Testing edge cases (1900 vs 2000)
Feature checklist
- Checks any year entered
- Applies the full Gregorian rule correctly
- Explains which rule decided the result
- Bonus: count leap years in a range
- Bonus: days until the next leap year
Starter code
#include <iostream>
bool isLeapYear(int year) {
// Divisible by 4, except centuries, unless divisible by 400
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main() {
int year;
std::cout << "Year: ";
if (!(std::cin >> year)) return 0;
if (isLeapYear(year))
std::cout << year << " is a leap year (366 days).\n";
else
std::cout << year << " is a common year (365 days).\n";
// How many leap years between 2000 and 2099?
int count = 0;
for (int y = 2000; y <= 2099; ++y) if (isLeapYear(y)) ++count;
std::cout << "Leap years in 2000-2099: " << count << "\n";
}Full walkthrough
Step 1: Learn the real rule before writing code
The Gregorian rule has three layers: a year is a leap year if divisible by 4 — EXCEPT years divisible by 100 — UNLESS they are also divisible by 400. 'Every 4 years' is the folk version; 1900 disproves it and 2000 refines it. The program's job is to apply all three layers and then EXPLAIN which one decided.
Step 2: Write isLeapYear() as one boolean expression
(y % 4 == 0 && y % 100 != 0) || y % 400 == 0. Read it as: 'a normal leap year, OR a super-leap century year'. One expression, no nested ifs — and every clause maps to one layer of the rule, so a reader can audit it against the rule in seconds.
bool isLeapYear(int y) {
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}Step 3: Explain the verdict, not just the verdict
The checklist wants the reason: after computing the answer, walk the layers again in words — if y % 400 == 0 print 'divisible by 400, so it IS a leap year'; else if y % 100 == 0 print 'divisible by 100 but not 400, so NOT'; else if y % 4 == 0 ... and so on. Duplicating the logic as narration feels wasteful until you realise the narration IS the feature.
Step 4: Build the simple main loop
Prompt 'Year (0 to quit): ', read an int, print the verdict with its reason, repeat. Keep main() dumb: all intelligence lives in isLeapYear() and the explainer, so the bonuses below can reuse them untouched.
Step 5: Bonus: count leap years in a range
Read a start and end year, loop between them, and count how often isLeapYear() returns true. This is your function proving its worth — the interesting part of the whole bonus is a one-line call inside a loop.
Step 6: Bonus: days until the next leap year
From a given year, walk forward year by year until isLeapYear() is true, then report when the next 29 February falls. Walking forward with the same predicate keeps one source of truth for what 'leap' means.
Step 7: Test the four canonical years
2024 → leap (plain divisible-by-4). 2023 → not. 1900 → NOT (the century trap). 2000 → leap (the 400 rescue). A leap-year checker that has not been fed 1900 and 2000 has not been tested at all — those two inputs are the entire reason the rule has layers.
Common mistakes
- Using only y % 4 == 0, which calls 1900 a leap year and fails the one test everyone tries.
- Writing the expression without parentheses so nobody reading it can tell whether the grouping was deliberate.
- Hard-coding the explanation to match only the final answer, so the narration contradicts the logic for century years.
Compile and run
g++ -std=c++17 -o leap_year leap_year.cppSample run
$ ./leap_year
Year (0 to quit):
> 2024
2024 IS a leap year — divisible by 4 and not by 100.
Year (0 to quit):
> 1900
1900 is NOT a leap year — divisible by 100 but not by 400.
Year (0 to quit):
> 2000
2000 IS a leap year — divisible by 400.
Year (0 to quit):
> 2023
2023 is NOT a leap year — not divisible by 4.
Count leap years in a range — from:
> 2020
to:
> 2030
Leap years between 2020 and 2030: 3 (2020, 2024, 2028)
Year (0 to quit):
> 0Try it in your browser
No browser demo is included for this project. Build the C++ version below — that is the real program.