C++ Fundamentals - III
This part of C++ fundamentals focuses on decision-making. In programming, a program often has to choose between different routes based on a condition. In flowcharts, this is usually represented using a diamond box: if the condition is true, one path is followed; if it is false, another path is followed. In C++, this selection logic is written using if, else, else if, nested conditions, and switch.
Decision Making with if and else
The if statement checks a condition. If the condition is true, the block of code inside it runs. If the condition is false, that block is skipped.
Consider a simple problem: input a person’s age and print Eligible if the age is greater than or equal to 18. Otherwise, print Not Eligible.
#include <iostream>using namespace std;int main() { int age; cin >> age; if (age >= 18) { cout << "Eligible"; } if (age < 18) { cout << "Not Eligible"; } return 0;}If the input is 14, the first condition age >= 18 is false, so the first block is skipped. The second condition age < 18 is true, so Not Eligible is printed.
If the input is 19, the first condition is true, so Eligible is printed. But after that, C++ still checks the second if. That second condition becomes false, so nothing more is printed. The result is correct, but the second check was unnecessary.
This is exactly where else becomes useful.
#include <iostream>using namespace std;int main() { int age; cin >> age; if (age >= 18) { cout << "Eligible"; } else { cout << "Not Eligible"; } return 0;}Now, if age >= 18 is true, the if block runs and the else block is skipped. If age >= 18 is false, the else block runs. This avoids writing a second condition for the opposite case.
Curly Braces with Single Statements
If an if or else contains only one statement, curly braces are technically optional.
if (age >= 18) cout << "Eligible";else cout << "Not Eligible";However, using braces is generally clearer and safer, especially for beginners. Once there are multiple statements to run inside a branch, braces are required to group them as one block.
if (age >= 18) { cout << "Eligible"; cout << "\nYou can vote.";}Problem: Positive, Negative, or Zero
Given an integer, print whether it is positive, negative, or zero.
Using Multiple if Statements
#include <iostream>using namespace std;int main() { int num; cin >> num; if (num == 0) { cout << "Zero"; } if (num > 0) { cout << "Positive"; } if (num < 0) { cout << "Negative"; } return 0;}This works, but it checks all three conditions independently. If num is 0, the first condition is true and Zero is printed. After that, C++ still checks whether num > 0 and whether num < 0, even though the answer is already known.
Using else if
#include <iostream>using namespace std;int main() { int num; cin >> num; if (num == 0) { cout << "Zero"; } else if (num > 0) { cout << "Positive"; } else { cout << "Negative"; } return 0;}This version is better. The chain is evaluated from top to bottom. Once a condition succeeds, its block runs and the rest of the chain is skipped.
Examples:
Input
0: the first condition is true, so output isZero.Input
12: the first condition is false, the second condition is true, so output isPositive.Input
-90: the first two conditions are false, so the finalelseruns and output isNegative.
Problem: Even or Odd
Given an integer, determine whether it is even or odd.
A number is odd if it leaves a remainder of 1 when divided by 2. The remainder operator % is used for this.
#include <iostream>using namespace std;int main() { int num; cin >> num; if (num % 2 == 1) { cout << "Odd"; } else { cout << "Even"; } return 0;}For input 12, 12 % 2 gives 0. The condition num % 2 == 1 is false, so the output is Even.
For input 17, 17 % 2 gives 1. The condition is true, so the output is Odd.
Problem: Largest of Two Integers
Given two integers, print the larger one. If both are equal, print Equal.
#include <iostream>using namespace std;int main() { int n1, n2; cin >> n1 >> n2; if (n1 > n2) { cout << n1; } else if (n2 > n1) { cout << n2; } else { cout << "Equal"; } return 0;}For input: 17 12, the first condition is true, so 17 is printed.
For input: 17 17, neither number is greater than the other, so the final else runs and Equal is printed.
if vs else if Chain
Multiple independent if statements are all checked separately. An if-else if chain stops after the first successful condition.
Consider temperature classification:
#include <iostream>using namespace std;int main() { int temp; cin >> temp; if (temp > 30) { cout << "Hot\n"; } if (temp > 20) { cout << "Warm\n"; } return 0;}If the input is 35, both conditions are true. The output becomes:
Hot
WarmThat may not be the intended result if only one category should be printed. In that case, use an else if chain:
#include <iostream>using namespace std;int main() { int temp; cin >> temp; if (temp > 30) { cout << "Hot"; } else if (temp > 20) { cout << "Warm"; } return 0;}Now, for input 35, only Hot is printed. Since the first condition succeeds, the second condition is skipped.
Branch Order Carries Information
In an else if chain, every branch knows that all previous conditions failed. This is an important idea. It allows us to avoid repeating unnecessary checks.
Problem: Grade Based on Marks
Given integer marks, print the grade based on these rules:
If marks are less than
0or greater than100, printInvalid.If marks are at least
90, printA.Else if marks are at least
75, printB.Else if marks are at least
60, printC.Else if marks are at least
40, printD.Otherwise, print
F.
The phrase “at least” means greater than or equal to.
#include <iostream>using namespace std;int main() { int marks; cin >> marks; if (marks < 0 || marks > 100) { cout << "Invalid"; } else if (marks >= 90) { cout << "A"; } else if (marks >= 75) { cout << "B"; } else if (marks >= 60) { cout << "C"; } else if (marks >= 40) { cout << "D"; } else { cout << "F"; } return 0;}Notice that the branch for B only checks: marks >= 75
It does not need to check: marks < 90
This is because the previous branch marks >= 90 has already failed. If execution reaches marks >= 75, it is already known that marks are less than 90.
For input 41, the evaluation goes like this:
marks < 0 || marks > 100is false.marks >= 90is false.marks >= 75is false.marks >= 60is false.marks >= 40is true, soDis printed.
When the program reaches the marks >= 40 branch, it already knows that marks are not 60 or above. So this branch effectively represents the range 40 to 59.
Common Wording in Conditions
At least 90 means
>= 90.More than 90 means
> 90.Below 40 means
< 40.From 0 to 100 inclusive means
>= 0and<= 100.Outside 0 to 100 means
< 0or> 100.
Problem: Largest of Three Numbers
Given three unique numbers, print the largest one. The assumption here is that all three numbers are different.
#include <iostream>using namespace std;int main() { int n1, n2, n3; cin >> n1 >> n2 >> n3; if (n1 > n2 && n1 > n3) { cout << n1; } else if (n2 > n3) { cout << n2; } else { cout << n3; } return 0;}The first condition checks whether n1 is greater than both n2 and n3. If true, n1 is the largest.
If the first condition fails, then n1 is not the largest. The largest must be either n2 or n3. So the next check only needs to compare n2 and n3.
Examples:
Input
4 5 6prints6.Input
12 4 7prints12.Input
12 14 7prints14.
Scalable Maximum Approach
Another way to find the maximum is to assume the first number is the current maximum, then let every next number challenge it.
#include <iostream>using namespace std;int main() { int n1, n2, n3; cin >> n1 >> n2 >> n3; int maximum = n1; if (n2 > maximum) { maximum = n2; } if (n3 > maximum) { maximum = n3; } cout << maximum; return 0;}This approach is easy to extend. For four, five, or many numbers, keep one variable as the current maximum and compare every new value with it. If the new value is larger, it becomes the new maximum.
Problem: Divisible by 3 and 5
Given one integer:
Print
Bothif it is divisible by both3and5.Print
3if it is divisible only by3.Print
5if it is divisible only by5.Print
Noneotherwise.
#include <iostream>using namespace std;int main() { int num; cin >> num; if (num % 3 == 0 && num % 5 == 0) { cout << "Both"; } else if (num % 3 == 0) { cout << "3"; } else if (num % 5 == 0) { cout << "5"; } else { cout << "None"; } return 0;}The first condition must check both divisibility rules using &&. Both conditions must be true for the number to be divisible by both 3 and 5.
Examples:
Input
15: divisible by both3and5, so output isBoth.Input
18: divisible only by3, so output is3.Input
20: divisible only by5, so output is5.Input
22: divisible by neither, so output isNone.
Nested Decisions
A nested decision means writing one decision inside another. If one condition is true, then inside that branch another condition may be checked.
if (condition1) { if (condition2) { // code }}This is valid because a block of code can contain any legal C++ statement, including another if.
ATM Example
An ATM flow is a natural example of nesting.
First, check whether the PIN is correct.
Only if the PIN is correct, allow the user to continue.
Then check whether the withdrawal amount is less than or equal to the balance.
If enough balance exists, allow withdrawal.
Otherwise, deny withdrawal.
#include <iostream>using namespace std;int main() { int enteredPin; int correctPin = 1234; int balance = 5000; int amount; cin >> enteredPin; if (enteredPin == correctPin) { cin >> amount; if (amount <= balance) { cout << "Withdrawal allowed"; } else { cout << "Insufficient balance"; } } else { cout << "Incorrect PIN"; } return 0;}Here, the balance check should happen only after the PIN is correct. That makes the second decision dependent on reaching the first successful route.
Nesting is useful, but very deep nesting becomes hard to read. Two or three levels may be manageable, but ten levels of nested if statements usually indicate poor structure.
Switch Case
A switch statement is useful when the output depends on one discrete value. A discrete value means a specific value such as 1, 2, 3, or a character such as '+', '-', '*', '/'.
It is often cleaner than writing many else if conditions when all checks compare the same variable against fixed values.
Problem: Day of the Week
Given a number from 1 to 7, print the corresponding day.
1means Monday.2means Tuesday.3means Wednesday.4means Thursday.5means Friday.6means Saturday.7means Sunday.
Using if-else
if (day == 1) { cout << "Monday";} else if (day == 2) { cout << "Tuesday";} else if (day == 3) { cout << "Wednesday";} else if (day == 4) { cout << "Thursday";} else if (day == 5) { cout << "Friday";} else if (day == 6) { cout << "Saturday";} else if (day == 7) { cout << "Sunday";} else { cout << "Invalid number";}This works, but every branch compares day with a fixed value. This is a good situation for switch.
Using switch
#include <iostream>using namespace std;int main() { int day; cin >> day; switch (day) { case 1: cout << "Monday"; break; case 2: cout << "Tuesday"; break; case 3: cout << "Wednesday"; break; case 4: cout << "Thursday"; break; case 5: cout << "Friday"; break; case 6: cout << "Saturday"; break; case 7: cout << "Sunday"; break; default: cout << "Invalid number"; } return 0;}The expression inside switch(day) is compared with the constant case labels. If day is 1, execution jumps to case 1. If day is 4, execution jumps to case 4.
Why break Is Important
If break is not written, execution falls through to the next case. For example:
switch (day) { case 1: cout << "Monday"; case 2: cout << "Tuesday"; case 3: cout << "Wednesday";}If day is 1, the program starts at case 1, prints Monday, then continues into case 2 and case 3. This is called fall-through.
Fall-through can be intentional in some cases, but accidental missing break statements are a very common beginner bug. In ordinary cases, write break after each case once that case’s work is complete.
Default Case
If none of the cases match, the default case runs.
default: cout << "Invalid number";For the day problem, if input is 9, none of the cases from 1 to 7 match, so Invalid number is printed.
When Switch Is Not the Right Fit
switch is not preferred for range checks or compound conditions.
// Better with if-else, not switchif (marks >= 90) { cout << "A";}switch also cannot be used directly on a string in C++. It works with integral-like discrete values such as int and char.
Problem: Simple Calculator
Input two numbers and an operator. Based on the operator, perform the operation on the two numbers.
Example Input: 2 9 +
Since the operator is +, the result is: 11
This problem is a good use case for switch because the operation depends on one discrete value: the operator character.
#include <iostream>using namespace std;int main() { double n1, n2; char op; cin >> n1 >> n2 >> op; switch (op) { case '+': cout << n1 + n2; break; case '-': cout << n1 - n2; break; case '*': cout << n1 * n2; break; case '/': if (n2 != 0) { cout << n1 / n2; } else { cout << "Division by zero is not allowed"; } break; default: cout << "Invalid operator"; } return 0;}The operator is stored in a char because symbols such as +, -, *, and / are characters. The switch compares op with each case label.
Examples:
Input
2 9 +prints11.Input
10 4 -prints6.Input
6 5 *prints30.Input
20 4 /prints5.Input
20 0 /prints a division-by-zero message.Input
20 4 %printsInvalid operatorin this version because%is not handled.
Input Validation
Input validation means checking whether the input is acceptable before using it. It has two important layers.
Representation Validation
Representation validation checks whether the input is of the expected type.
For example, if a problem says marks will be an integer, then representation validation asks: did the input actually contain an integer, or did it contain something else such as text?
int marks;if (cin >> marks) { cout << "Integer input received";} else { cout << "Invalid representation";}If the input is 85, extraction succeeds. If the input is hello, extraction fails because hello cannot be stored in an int.
Domain Validation
Domain validation checks whether the value lies in the valid range for the problem.
For marks, even if the input is an integer, it must usually be between 0 and 100.
int marks;cin >> marks;if (marks < 0 || marks > 100) { cout << "Invalid";} else { cout << "Valid";}Here, 150 is a valid integer representation, but it is not valid marks in the domain of the problem.
Validation in Interviews and Online Judges
In interviews, validation matters because input constraints may not always be fully stated. It is good practice to ask what inputs are possible and whether invalid cases should be handled. Checking both representation and domain shows careful thinking.
In online judges, constraints are usually guaranteed. If the problem statement says the input will be an integer between 0 and 100, then test cases will respect that unless invalid input handling is explicitly part of the problem. In such cases, extra checks are often unnecessary and may even produce output that the judge does not expect.
Key Takeaways
ifruns a block only when its condition is true.elsehandles the opposite route when theifcondition fails.else ifis used when there are multiple mutually exclusive conditions.Multiple independent
ifstatements are all checked separately.An
if-else ifchain stops after the first successful branch.Branch order carries information because each later branch knows previous checks failed.
Nested decisions are valid, but excessive nesting hurts readability.
switchis useful when one discrete value decides the action.breakprevents accidental fall-through in switch cases.defaulthandles values that do not match any case.Validation has two layers: representation validation and domain validation.
Be the first to add a comment.