cpp
exercises
exercises.cpp⚙️cpp
/**
* C++ Operators - Exercises
*
* Practice problems to reinforce understanding of C++ operators.
* Each exercise includes a description, TODO section, and hints.
* Complete solutions are provided in the ANSWER KEY at the bottom.
*
* Difficulty Levels:
* ⭐ - Beginner
* ⭐⭐ - Intermediate
* ⭐⭐⭐ - Advanced
*
* Compile: g++ -std=c++17 -Wall -Wextra exercises.cpp -o exercises
* Run: ./exercises
*/
#include <iostream>
#include <cmath>
#include <string>
#include <bitset>
using namespace std;
// ============================================================
// Exercise 1: Basic Calculator ⭐
// ============================================================
/**
* Create a function that takes two numbers and an operator character
* (+, -, *, /, %) and returns the result of the operation.
* Handle division by zero by returning 0.
*
* Examples:
* calculate(10, 5, '+') returns 15
* calculate(10, 5, '-') returns 5
* calculate(10, 3, '/') returns 3
* calculate(10, 0, '/') returns 0 (division by zero)
*/
double calculate(double a, double b, char op) {
// TODO: Implement the calculator function
// Hint: Use if-else or switch statement
// Hint: Check for division by zero before dividing
return 0; // Replace with your implementation
}
// ============================================================
// Exercise 2: Check Number Properties ⭐
// ============================================================
/**
* Create a function that checks if a number is:
* - Positive, negative, or zero
* - Even or odd (for non-zero integers)
*
* Return a string describing all properties.
*
* Examples:
* checkNumber(5) returns "positive odd"
* checkNumber(-4) returns "negative even"
* checkNumber(0) returns "zero"
*/
string checkNumber(int n) {
// TODO: Implement the function
// Hint: Use relational operators (>, <, ==)
// Hint: Use modulus operator (%) to check even/odd
return ""; // Replace with your implementation
}
// ============================================================
// Exercise 3: Range Checker ⭐
// ============================================================
/**
* Create a function that checks if a number is within a given range
* (inclusive on both ends).
*
* Examples:
* inRange(5, 1, 10) returns true (5 is between 1 and 10)
* inRange(0, 1, 10) returns false (0 is not between 1 and 10)
* inRange(10, 1, 10) returns true (10 is on the boundary)
*/
bool inRange(int value, int min, int max) {
// TODO: Implement the function
// Hint: Use logical AND (&&) with relational operators
return false; // Replace with your implementation
}
// ============================================================
// Exercise 4: Leap Year Checker ⭐⭐
// ============================================================
/**
* Create a function that checks if a year is a leap year.
*
* Rules:
* - Divisible by 4 AND not divisible by 100, OR
* - Divisible by 400
*
* Examples:
* isLeapYear(2024) returns true
* isLeapYear(2023) returns false
* isLeapYear(2000) returns true (divisible by 400)
* isLeapYear(1900) returns false (divisible by 100 but not 400)
*/
bool isLeapYear(int year) {
// TODO: Implement the function
// Hint: Use modulus (%) and logical operators (&&, ||)
return false; // Replace with your implementation
}
// ============================================================
// Exercise 5: Grade Calculator with Ternary ⭐⭐
// ============================================================
/**
* Create a function that returns a letter grade based on a score
* using ONLY the ternary operator (no if-else statements).
*
* 90-100: A
* 80-89: B
* 70-79: C
* 60-69: D
* Below 60: F
*
* Examples:
* getGrade(95) returns 'A'
* getGrade(82) returns 'B'
* getGrade(55) returns 'F'
*/
char getGrade(int score) {
// TODO: Implement using ONLY ternary operators (nested ? :)
// Hint: condition1 ? 'A' : condition2 ? 'B' : ...
return 'F'; // Replace with your implementation
}
// ============================================================
// Exercise 6: Bit Counter ⭐⭐
// ============================================================
/**
* Create a function that counts the number of 1 bits (set bits)
* in an unsigned integer.
*
* Examples:
* countBits(5) returns 2 (5 = 101 in binary)
* countBits(7) returns 3 (7 = 111 in binary)
* countBits(0) returns 0
* countBits(255) returns 8 (255 = 11111111 in binary)
*/
int countBits(unsigned int n) {
// TODO: Implement the function
// Hint: Use a loop with bitwise AND (&) and right shift (>>)
// Hint: n & 1 gives the last bit
return 0; // Replace with your implementation
}
// ============================================================
// Exercise 7: Power of Two Checker ⭐⭐
// ============================================================
/**
* Create a function that checks if a positive integer is a power of 2.
* Use ONLY bitwise operators (no loops, no division).
*
* Powers of 2: 1, 2, 4, 8, 16, 32, ...
*
* Examples:
* isPowerOfTwo(1) returns true (2^0)
* isPowerOfTwo(16) returns true (2^4)
* isPowerOfTwo(18) returns false
* isPowerOfTwo(0) returns false
*
* Hint: Think about the binary representation of powers of 2.
* 1 = 0001, 2 = 0010, 4 = 0100, 8 = 1000
* What happens when you do n & (n-1)?
*/
bool isPowerOfTwo(unsigned int n) {
// TODO: Implement using bitwise operators only
// Hint: For power of 2, only one bit is set
// Hint: n & (n-1) removes the lowest set bit
return false; // Replace with your implementation
}
// ============================================================
// Exercise 8: Swap Using XOR ⭐⭐
// ============================================================
/**
* Create a function that swaps two integers WITHOUT using a temporary
* variable. Use XOR bitwise operator.
*
* After calling swap(a, b):
* Original values should be exchanged.
*/
void swapXOR(int& a, int& b) {
// TODO: Swap a and b using only XOR (^) operator
// Hint: XOR has a special property: x ^ x = 0 and x ^ 0 = x
// Hint: Three XOR operations are needed
// Your code here
}
// ============================================================
// Exercise 9: Bit Manipulation ⭐⭐⭐
// ============================================================
/**
* Create functions to:
* a) Set the nth bit (make it 1)
* b) Clear the nth bit (make it 0)
* c) Toggle the nth bit (flip it)
* d) Check if the nth bit is set
*
* Note: Bits are 0-indexed from the right.
*
* Examples:
* setBit(5, 1) returns 7 (101 -> 111)
* clearBit(7, 1) returns 5 (111 -> 101)
* toggleBit(5, 0) returns 4 (101 -> 100)
* isBitSet(5, 2) returns true (bit 2 of 101 is 1)
*/
unsigned int setBit(unsigned int n, int pos) {
// TODO: Set bit at position pos
// Hint: Use OR with a mask
return n; // Replace with your implementation
}
unsigned int clearBit(unsigned int n, int pos) {
// TODO: Clear bit at position pos
// Hint: Use AND with inverted mask
return n; // Replace with your implementation
}
unsigned int toggleBit(unsigned int n, int pos) {
// TODO: Toggle bit at position pos
// Hint: Use XOR with a mask
return n; // Replace with your implementation
}
bool isBitSet(unsigned int n, int pos) {
// TODO: Check if bit at position pos is set
// Hint: Use AND with a mask, then check if non-zero
return false; // Replace with your implementation
}
// ============================================================
// Exercise 10: Approximate Float Comparison ⭐⭐⭐
// ============================================================
/**
* Create a function that compares two floating-point numbers
* for approximate equality using both absolute and relative epsilon.
*
* Two numbers are approximately equal if:
* - Their absolute difference is less than absolute epsilon, OR
* - Their relative difference is less than relative epsilon
*
* Use abs_epsilon = 1e-12 and rel_epsilon = 1e-9
*
* Examples:
* approxEqual(0.1 + 0.2, 0.3) returns true
* approxEqual(1000000.0, 1000000.1) may return true (relative)
* approxEqual(1.0, 2.0) returns false
*/
bool approxEqual(double a, double b) {
// TODO: Implement approximate equality comparison
// Hint: Use fabs() for absolute value
// Hint: For relative epsilon, divide by max(|a|, |b|)
const double ABS_EPSILON = 1e-12;
const double REL_EPSILON = 1e-9;
return false; // Replace with your implementation
}
// ============================================================
// BONUS Exercise: Expression Evaluator ⭐⭐⭐
// ============================================================
/**
* Create a function that evaluates a simple expression with proper
* operator precedence. The expression contains only single-digit
* numbers and +, -, *, / operators.
*
* This is a challenging exercise that requires understanding of
* operator precedence and parsing.
*
* Examples:
* evaluate("2+3*4") returns 14 (not 20)
* evaluate("8/2+3") returns 7
* evaluate("1+2+3") returns 6
*/
double evaluate(const string& expr) {
// TODO: Implement expression evaluation with precedence
// This is optional and challenging!
// Hint: Handle *, / first, then +, -
return 0; // Replace with your implementation
}
// ============================================================
// Test Functions
// ============================================================
void testExercise1() {
cout << "\n=== Testing Exercise 1: Basic Calculator ===" << endl;
cout << "calculate(10, 5, '+') = " << calculate(10, 5, '+') << " (expected: 15)" << endl;
cout << "calculate(10, 5, '-') = " << calculate(10, 5, '-') << " (expected: 5)" << endl;
cout << "calculate(10, 5, '*') = " << calculate(10, 5, '*') << " (expected: 50)" << endl;
cout << "calculate(10, 3, '/') = " << calculate(10, 3, '/') << " (expected: 3.33...)" << endl;
cout << "calculate(10, 3, '%') = " << calculate(10, 3, '%') << " (expected: 1)" << endl;
cout << "calculate(10, 0, '/') = " << calculate(10, 0, '/') << " (expected: 0)" << endl;
}
void testExercise2() {
cout << "\n=== Testing Exercise 2: Check Number Properties ===" << endl;
cout << "checkNumber(5) = \"" << checkNumber(5) << "\" (expected: \"positive odd\")" << endl;
cout << "checkNumber(-4) = \"" << checkNumber(-4) << "\" (expected: \"negative even\")" << endl;
cout << "checkNumber(0) = \"" << checkNumber(0) << "\" (expected: \"zero\")" << endl;
cout << "checkNumber(8) = \"" << checkNumber(8) << "\" (expected: \"positive even\")" << endl;
}
void testExercise3() {
cout << "\n=== Testing Exercise 3: Range Checker ===" << endl;
cout << boolalpha;
cout << "inRange(5, 1, 10) = " << inRange(5, 1, 10) << " (expected: true)" << endl;
cout << "inRange(0, 1, 10) = " << inRange(0, 1, 10) << " (expected: false)" << endl;
cout << "inRange(10, 1, 10) = " << inRange(10, 1, 10) << " (expected: true)" << endl;
cout << "inRange(15, 1, 10) = " << inRange(15, 1, 10) << " (expected: false)" << endl;
}
void testExercise4() {
cout << "\n=== Testing Exercise 4: Leap Year Checker ===" << endl;
cout << boolalpha;
cout << "isLeapYear(2024) = " << isLeapYear(2024) << " (expected: true)" << endl;
cout << "isLeapYear(2023) = " << isLeapYear(2023) << " (expected: false)" << endl;
cout << "isLeapYear(2000) = " << isLeapYear(2000) << " (expected: true)" << endl;
cout << "isLeapYear(1900) = " << isLeapYear(1900) << " (expected: false)" << endl;
}
void testExercise5() {
cout << "\n=== Testing Exercise 5: Grade Calculator ===" << endl;
cout << "getGrade(95) = '" << getGrade(95) << "' (expected: 'A')" << endl;
cout << "getGrade(82) = '" << getGrade(82) << "' (expected: 'B')" << endl;
cout << "getGrade(75) = '" << getGrade(75) << "' (expected: 'C')" << endl;
cout << "getGrade(65) = '" << getGrade(65) << "' (expected: 'D')" << endl;
cout << "getGrade(55) = '" << getGrade(55) << "' (expected: 'F')" << endl;
}
void testExercise6() {
cout << "\n=== Testing Exercise 6: Bit Counter ===" << endl;
cout << "countBits(5) = " << countBits(5) << " (expected: 2, binary: 101)" << endl;
cout << "countBits(7) = " << countBits(7) << " (expected: 3, binary: 111)" << endl;
cout << "countBits(0) = " << countBits(0) << " (expected: 0)" << endl;
cout << "countBits(255) = " << countBits(255) << " (expected: 8, binary: 11111111)" << endl;
}
void testExercise7() {
cout << "\n=== Testing Exercise 7: Power of Two ===" << endl;
cout << boolalpha;
cout << "isPowerOfTwo(1) = " << isPowerOfTwo(1) << " (expected: true)" << endl;
cout << "isPowerOfTwo(16) = " << isPowerOfTwo(16) << " (expected: true)" << endl;
cout << "isPowerOfTwo(18) = " << isPowerOfTwo(18) << " (expected: false)" << endl;
cout << "isPowerOfTwo(0) = " << isPowerOfTwo(0) << " (expected: false)" << endl;
}
void testExercise8() {
cout << "\n=== Testing Exercise 8: XOR Swap ===" << endl;
int a = 5, b = 10;
cout << "Before swap: a = " << a << ", b = " << b << endl;
swapXOR(a, b);
cout << "After swap: a = " << a << ", b = " << b << " (expected: a=10, b=5)" << endl;
}
void testExercise9() {
cout << "\n=== Testing Exercise 9: Bit Manipulation ===" << endl;
cout << "setBit(5, 1) = " << setBit(5, 1) << " (expected: 7, " << bitset<4>(5) << " -> " << bitset<4>(7) << ")" << endl;
cout << "clearBit(7, 1) = " << clearBit(7, 1) << " (expected: 5, " << bitset<4>(7) << " -> " << bitset<4>(5) << ")" << endl;
cout << "toggleBit(5, 0) = " << toggleBit(5, 0) << " (expected: 4, " << bitset<4>(5) << " -> " << bitset<4>(4) << ")" << endl;
cout << boolalpha;
cout << "isBitSet(5, 2) = " << isBitSet(5, 2) << " (expected: true)" << endl;
cout << "isBitSet(5, 1) = " << isBitSet(5, 1) << " (expected: false)" << endl;
}
void testExercise10() {
cout << "\n=== Testing Exercise 10: Approximate Float Comparison ===" << endl;
cout << boolalpha;
cout << "approxEqual(0.1 + 0.2, 0.3) = " << approxEqual(0.1 + 0.2, 0.3) << " (expected: true)" << endl;
cout << "approxEqual(1.0, 2.0) = " << approxEqual(1.0, 2.0) << " (expected: false)" << endl;
cout << "approxEqual(1000000.0, 1000000.0000001) = " << approxEqual(1000000.0, 1000000.0000001) << " (expected: true)" << endl;
}
void testBonus() {
cout << "\n=== Testing BONUS: Expression Evaluator ===" << endl;
cout << "evaluate(\"2+3*4\") = " << evaluate("2+3*4") << " (expected: 14)" << endl;
cout << "evaluate(\"8/2+3\") = " << evaluate("8/2+3") << " (expected: 7)" << endl;
cout << "evaluate(\"1+2+3\") = " << evaluate("1+2+3") << " (expected: 6)" << endl;
}
// ============================================================
// Main Function
// ============================================================
int main() {
cout << "╔════════════════════════════════════════════════════════════╗" << endl;
cout << "║ C++ OPERATORS - EXERCISES ║" << endl;
cout << "╚════════════════════════════════════════════════════════════╝" << endl;
testExercise1();
testExercise2();
testExercise3();
testExercise4();
testExercise5();
testExercise6();
testExercise7();
testExercise8();
testExercise9();
testExercise10();
testBonus();
cout << "\n╔════════════════════════════════════════════════════════════╗" << endl;
cout << "║ Complete the TODO sections and re-run! ║" << endl;
cout << "╚════════════════════════════════════════════════════════════╝" << endl;
return 0;
}
// ============================================================
// ANSWER KEY
// ============================================================
/*
* Below are the complete solutions for all exercises.
* Try to solve them yourself first before looking!
*/
/*
// Exercise 1: Basic Calculator
double calculate(double a, double b, char op) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return (b != 0) ? a / b : 0;
case '%': return (b != 0) ? static_cast<int>(a) % static_cast<int>(b) : 0;
default: return 0;
}
}
// Exercise 2: Check Number Properties
string checkNumber(int n) {
if (n == 0) return "zero";
string result = (n > 0) ? "positive " : "negative ";
result += (n % 2 == 0) ? "even" : "odd";
return result;
}
// Exercise 3: Range Checker
bool inRange(int value, int min, int max) {
return value >= min && value <= max;
}
// Exercise 4: Leap Year Checker
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// Exercise 5: Grade Calculator
char getGrade(int score) {
return (score >= 90) ? 'A' :
(score >= 80) ? 'B' :
(score >= 70) ? 'C' :
(score >= 60) ? 'D' : 'F';
}
// Exercise 6: Bit Counter
int countBits(unsigned int n) {
int count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
// Exercise 7: Power of Two
bool isPowerOfTwo(unsigned int n) {
return n > 0 && (n & (n - 1)) == 0;
}
// Exercise 8: XOR Swap
void swapXOR(int& a, int& b) {
if (&a != &b) { // Avoid self-swap issues
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
}
// Exercise 9: Bit Manipulation
unsigned int setBit(unsigned int n, int pos) {
return n | (1 << pos);
}
unsigned int clearBit(unsigned int n, int pos) {
return n & ~(1 << pos);
}
unsigned int toggleBit(unsigned int n, int pos) {
return n ^ (1 << pos);
}
bool isBitSet(unsigned int n, int pos) {
return (n & (1 << pos)) != 0;
}
// Exercise 10: Approximate Float Comparison
bool approxEqual(double a, double b) {
const double ABS_EPSILON = 1e-12;
const double REL_EPSILON = 1e-9;
double diff = fabs(a - b);
// Check absolute difference
if (diff < ABS_EPSILON) return true;
// Check relative difference
double larger = max(fabs(a), fabs(b));
if (larger > 0 && diff / larger < REL_EPSILON) return true;
return false;
}
// BONUS: Expression Evaluator (simplified version)
double evaluate(const string& expr) {
vector<double> nums;
vector<char> ops;
// Parse the expression
for (size_t i = 0; i < expr.length(); i++) {
if (isdigit(expr[i])) {
nums.push_back(expr[i] - '0');
} else if (expr[i] == '+' || expr[i] == '-' ||
expr[i] == '*' || expr[i] == '/') {
ops.push_back(expr[i]);
}
}
// First pass: handle * and /
for (size_t i = 0; i < ops.size(); ) {
if (ops[i] == '*' || ops[i] == '/') {
double result = (ops[i] == '*') ?
nums[i] * nums[i+1] : nums[i] / nums[i+1];
nums[i] = result;
nums.erase(nums.begin() + i + 1);
ops.erase(ops.begin() + i);
} else {
i++;
}
}
// Second pass: handle + and -
double result = nums[0];
for (size_t i = 0; i < ops.size(); i++) {
if (ops[i] == '+') result += nums[i+1];
else if (ops[i] == '-') result -= nums[i+1];
}
return result;
}
*/