๐ Setting Up a Real Project
The Pre-Course had you compile one file by hand. From here on, you'll want a slightly more organized habit โ the same one you'll use for every project in this entire roadmap.
Create a new folder for each program you build in this course โ for example, cpp-projects/phase1-fundamentals/. Inside it, your main source file is still just main.cpp, compiled and run exactly the way you learned in the Pre-Course: g++ main.cpp -o program, then ./program.
A comment is text in your source file the compiler completely ignores โ it's there purely for humans reading the code (including future-you).
// A single-line comment /* A multi-line comment that spans several lines */
// add 1 to score next to score++; tells you nothing the code doesn't already say. A comment explaining WHY โ "cap score at 100 so the UI bar never overflows" โ is what actually helps someone (including you, in six months) understand a decision the code alone can't show.๐ฆ Variables & Data Types, For Real
The Pre-Course introduced variables as labeled boxes. Now let's cover every core type you'll actually use, and exactly what each one holds.
| Type | Holds | Example |
|---|---|---|
int | A whole number | int age = 25; |
double | A decimal number | double price = 19.99; |
char | A single character | char grade = 'A'; |
bool | true or false | bool isOpen = true; |
std::string | Text of any length | std::string name = "Alex"; |
'A' (single quotes) is a char โ exactly one character. "A" (double quotes) is a std::string โ text, even if it's only one character long. Mixing these up is a genuinely common early mistake that produces a real compiler error, not just a style issue.Every type reserves a specific amount of memory. An int typically uses 4 bytes, giving it a fixed range it can represent (roughly -2 billion to +2 billion). If a calculation produces a number outside that range, it overflows โ silently wrapping around to an incorrect value, without any error or warning. This is exactly why C++ offers multiple whole-number types (short, int, long, long long) of different sizes โ you pick based on the range of values you actually need.
Variable names must start with a letter or underscore, can contain letters/numbers/underscores, and are case-sensitive (score and Score are two different variables). The convention in C++ is camelCase for variable names โ totalScore, not total_score or TotalScore โ though the compiler itself doesn't enforce this; it's a team/community convention worth following anyway.
'A' and "A" in C++?๐ Constants & Literals
Not every value should be changeable. This lesson covers how to lock a value in place on purpose โ and why that's a genuinely good habit, not just a restriction.
const double PI = 3.14159; const int MAX_PLAYERS = 4;
Adding const before a variable's type tells the compiler "this value is set once, right here, and can never change again." If your code later tries to assign a new value to PI, the compiler will refuse to compile it โ catching that mistake for you, before your program ever runs.
- It documents intent. Seeing
consttells anyone reading the code "this is never supposed to change" โ without needing a comment to say so. - It prevents real bugs. If you accidentally write code that changes a value that should never change, the compiler catches it immediately instead of you discovering it much later as confusing, hard-to-trace behavior.
The convention is to name constants in ALL_CAPS_WITH_UNDERSCORES โ this makes them instantly recognizable at a glance, distinct from regular variables.
A literal is a value written directly into your code, rather than stored in a variable โ the 5 in int score = 5; is a literal. You've been using literals since the Pre-Course without a name for them; this lesson just gives you the vocabulary.
const?โ Arithmetic Operators
The actual math symbols C++ uses โ mostly familiar, with two genuine surprises worth knowing before they confuse you.
| Operator | Meaning | Example |
|---|---|---|
+ | Addition | 5 + 3 โ 8 |
- | Subtraction | 5 - 3 โ 2 |
* | Multiplication | 5 * 3 โ 15 |
/ | Division | 10 / 3 โ 3 (see below!) |
% | Modulo (remainder) | 10 % 3 โ 1 |
When both numbers involved in division are int, C++ performs integer division: it throws away any decimal remainder entirely, rather than rounding. 10 / 3 gives 3, not 3.333. To get a decimal result, at least one of the numbers involved needs to actually be a double.
int a = 10, b = 3; std::cout << a / b; // prints 3 std::cout << (double)a / b; // prints 3.33333
% gives you the remainder after division โ 10 % 3 is 1, because 3 goes into 10 three times with 1 left over. This shows up constantly in real code: checking if a number is even (n % 2 == 0), wrapping an index around an array's bounds, or converting a total number of seconds into hours/minutes/seconds.
7 / 2 evaluate to in C++, if both 7 and 2 are written as plain int values?โ๏ธ Comparison & Logical Operators
How C++ actually checks the "yes or no" conditions you learned about conceptually in the Pre-Course.
| Operator | Meaning |
|---|---|
== | Equal to |
!= | Not equal to |
> / < | Greater than / less than |
>= / <= | Greater than or equal / less than or equal |
= assigns a value ("put this in the box"). == compares two values ("are these equal?"). Writing if (score = 100) instead of if (score == 100) is legal C++ that does something completely different than intended โ it ASSIGNS 100 to score and then checks if that assignment succeeded, which is almost never what you meant. Most modern compilers will warn you about this specific mistake.| Operator | Meaning | Example |
|---|---|---|
&& | AND โ both must be true | age >= 18 && hasLicense |
|| | OR โ at least one must be true | isWeekend || isHoliday |
! | NOT โ flips true to false and vice versa | !isLoggedIn |
These directly implement the "if it's raining AND I don't have a car" example from the Pre-Course โ you're now seeing the real C++ symbols for exactly that logic.
C++ is smart about && and ||: for &&, if the first condition is already false, C++ doesn't even bother checking the second one โ the overall result is already known to be false. This is called short-circuit evaluation, and it's more than just an efficiency trick: it's genuinely useful for writing safe checks, like hasAccount && account.balance > 0 โ if hasAccount is false, C++ never even attempts to check account.balance, avoiding a potential error from checking something that might not exist.
if (score = 100) when you meant to check whether score equals 100?โจ๏ธ Input & Output with cin/cout
Every program in this course so far has only ever printed fixed text. Real programs react to what the user actually types โ here's how.
You've used std::cout since Hello World. The << symbol "sends" a value to the output โ you can chain several in one line:
int score = 95; std::cout << "Your score is: " << score << std::endl;
int age; std::cout << "Enter your age: "; std::cin >> age; std::cout << "You are " << age << " years old." << std::endl;
std::cin pauses your program and waits for the user to type something and press Enter. Notice the arrow direction flips: >> for input (data flows INTO your variable), << for output (data flows OUT to the screen).
std::cin >> someString only reads a single word โ it stops at the first space. To read an entire line of text (like a full name), use std::getline instead:
std::string fullName;
std::cout << "Enter your full name: ";
std::getline(std::cin, fullName);
std::cin >> name fail to capture someone's full name if they type "Jude Baffoe"?๐ Type Conversion & Casting
You already saw one cast in Module 4's integer-division example. Here's the full picture of how C++ converts between types โ automatically, and on purpose.
C++ sometimes converts a value's type automatically, without you asking:
double price = 10; // int 10 automatically becomes 10.0 int total = 9.9; // double 9.9 automatically becomes 9 (truncated!)
double into an int truncates the decimal part with zero warning โ 9.9 becomes 9, not an error, not a rounded 10. This is a genuinely common source of subtle bugs, especially with money-related calculations.An explicit cast tells C++ "yes, I know this converts types, do it anyway" โ making your intent clear in the code itself:
int a = 7, b = 2; double result = static_cast<double>(a) / b; // 3.5, not 3
static_cast<double>(a) is the modern, preferred C++ way to explicitly convert a's type to double before the division happens โ solving the exact integer-division surprise from Module 4, deliberately and visibly.
๐ if/else in Depth
The Pre-Course showed you the shape of if/else. Now let's cover everything you'll actually need to use it confidently in real code.
if (score >= 90) { grade = 'A'; } else if (score >= 80) { grade = 'B'; } else if (score >= 70) { grade = 'C'; } else { grade = 'F'; }
C++ checks each condition in order and stops at the FIRST one that's true โ if score is 95, it matches the first condition and never even looks at the rest. The order of your conditions genuinely matters.
For a simple "pick one of two values" decision, C++ offers a shorter form:
// Long form: std::string status; if (age >= 18) { status = "adult"; } else { status = "minor"; } // Ternary shortcut, same result: std::string status = (age >= 18) ? "adult" : "minor";
Read condition ? valueIfTrue : valueIfFalse exactly like that. It's purely a shorthand for a simple two-way choice โ anything more complex should stay a regular if/else for readability.
Without curly braces, if only applies to the single NEXT line โ not everything visually indented under it:
if (score > 100) std::cout << "High score!"; score = 100; // this ALWAYS runs, regardless of the if!
if(...) is conditional unless you wrap the block in { }. Making braces a habit from day one avoids this exact class of bug entirely.๐ switch Statements
A long chain of else-if statements, all checking the SAME variable against different exact values, has a cleaner alternative.
switch (dayNumber) { case 1: std::cout << "Monday"; break; case 2: std::cout << "Tuesday"; break; default: std::cout << "Some other day"; }
switch only works for checking one variable against exact, specific values โ not ranges or complex conditions. That's exactly what makes it a good fit here (a day number matching an exact case) and a bad fit for something like grade ranges from the last lesson.
Without break, C++ doesn't stop after a matching case โ it keeps running every subsequent case's code too, until it hits a break or reaches the end. This is called fall-through, and while occasionally intentional, it's a very common source of bugs when accidentally forgotten.
switch (dayNumber) { case 1: std::cout << "Monday"; // missing break! falls through to case 2 too case 2: std::cout << "Tuesday"; break; }
๐ Capstone โ A Simple Calculator
Every idea from this phase, combined into one real program: variables, operators, cin/cout, casting, and a decision structure โ your first genuinely complete C++ program.
Build a calculator that asks the user for two numbers and an operator (+, -, *, or /), then prints the result โ handling the specific gotchas covered in this phase along the way.
#include <iostream> int main() { double num1, num2; char op; std::cout << "Enter first number: "; std::cin >> num1; std::cout << "Enter an operator (+, -, *, /): "; std::cin >> op; std::cout << "Enter second number: "; std::cin >> num2; double result; bool valid = true; if (op == '+') { result = num1 + num2; } else if (op == '-') { result = num1 - num2; } else if (op == '*') { result = num1 * num2; } else if (op == '/') { if (num2 == 0) { std::cout << "Error: cannot divide by zero." << std::endl; valid = false; } else { result = num1 / num2; } } else { std::cout << "Error: unknown operator." << std::endl; valid = false; } if (valid) { std::cout << "Result: " << result << std::endl; } return 0; }
num1andnum2aredouble, notintโ so the calculator handles decimal input correctly, and division (Module 4's integer-division trap) produces accurate results automatically.- Division by zero is checked explicitly BEFORE dividing โ a real, necessary safeguard, not just defensive-programming paranoia.
- The
validflag prevents printing a meaningless "Result:" line when an error already occurred โ the if/else structure from Module 8, doing real work.
Extend the Calculator
Before checking the reference solution, try building your own version. Then, once it works, extend it: add support for % (modulo, Module 4), and use a switch statement (Module 9) instead of if/else if for the operator check. Getting the same correct result via two different structures is exactly the kind of repetition that cements a new concept.