cpp
exercises
exercises.cpp⚙️cpp
/**
* Exception Handling - Exercises
* Compile: g++ -std=c++17 -Wall exercises.cpp -o exercises
*/
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
// ============================================================
// Exercise 1: Safe Division ⭐
// ============================================================
// TODO: Create safeDivide(a, b) that throws invalid_argument
// if b is zero. Test with try-catch.
void exercise1() {
// try {
// cout << safeDivide(10, 2) << endl; // 5
// cout << safeDivide(10, 0) << endl; // throws
// } catch (const invalid_argument& e) { ... }
cout << "(Implement safeDivide)" << endl;
}
// ============================================================
// Exercise 2: Range Validator ⭐⭐
// ============================================================
// TODO: Create validateRange(value, min, max) that throws
// out_of_range if value is not in [min, max]
void exercise2() {
// validateRange(50, 1, 100); // OK
// validateRange(150, 1, 100); // throws
cout << "(Implement validateRange)" << endl;
}
// ============================================================
// Exercise 3: Custom Exception Class ⭐⭐
// ============================================================
// TODO: Create NegativeValueException that stores the
// negative value that caused the error
void exercise3() {
// throw NegativeValueException(-5);
// catch: e.what() returns message
// e.getValue() returns -5
cout << "(Implement NegativeValueException)" << endl;
}
// ============================================================
// Exercise 4: Exception Chain ⭐⭐
// ============================================================
// TODO: Create 3 functions that call each other
// Inner throws, middle logs and rethrows, outer catches
void exercise4() {
// outer() catches from middle() which catches from inner()
cout << "(Implement exception chain)" << endl;
}
// ============================================================
// Exercise 5: Multiple Exception Types ⭐⭐⭐
// ============================================================
// TODO: Create function that can throw different exceptions
// based on error code. Handle each type differently.
void exercise5() {
// processError(1) -> throws invalid_argument
// processError(2) -> throws out_of_range
// processError(3) -> throws runtime_error
cout << "(Implement multiple exception types)" << endl;
}
// ============================================================
// Exercise 6: Exception-Safe Stack ⭐⭐⭐
// ============================================================
// TODO: Create Stack class that throws on pop() when empty
// and on push() when full (fixed size)
void exercise6() {
// Stack<int, 3> s;
// s.pop(); // throws "Stack empty"
// s.push(1); s.push(2); s.push(3);
// s.push(4); // throws "Stack full"
cout << "(Implement exception-safe Stack)" << endl;
}
// ============================================================
// Exercise 7: Resource Manager ⭐⭐⭐
// ============================================================
// TODO: Create RAII wrapper that demonstrates proper
// cleanup even when exceptions occur
void exercise7() {
// ResourceGuard acquires resource in ctor
// releases in dtor, even on exception
cout << "(Implement ResourceGuard RAII)" << endl;
}
// ============================================================
// Exercise 8: Validation System ⭐⭐⭐
// ============================================================
// TODO: Create validation system with multiple exception types
// - EmptyFieldException
// - InvalidFormatException
// - OutOfRangeException
// Each with relevant error information
void exercise8() {
// validate("", "email"); // EmptyFieldException
// validate("invalid", "email"); // InvalidFormatException
// validate("-5", "age"); // OutOfRangeException
cout << "(Implement validation exception system)" << endl;
}
// ============================================================
// MAIN
// ============================================================
int main() {
cout << "=== Exception Handling Exercises ===" << endl;
cout << "\nEx1: Safe Division" << endl;
exercise1();
cout << "\nEx2: Range Validator" << endl;
exercise2();
cout << "\nEx3: Custom Exception" << endl;
exercise3();
cout << "\nEx4: Exception Chain" << endl;
exercise4();
cout << "\nEx5: Multiple Types" << endl;
exercise5();
cout << "\nEx6: Exception-Safe Stack" << endl;
exercise6();
cout << "\nEx7: Resource Manager" << endl;
exercise7();
cout << "\nEx8: Validation System" << endl;
exercise8();
return 0;
}
// ============================================================
// ANSWERS
// ============================================================
/*
Ex1:
double safeDivide(double a, double b) {
if (b == 0) throw invalid_argument("Division by zero");
return a / b;
}
Ex2:
void validateRange(int value, int min, int max) {
if (value < min || value > max) {
throw out_of_range("Value " + to_string(value) +
" not in range [" + to_string(min) + "," + to_string(max) + "]");
}
}
Ex3:
class NegativeValueException : public exception {
int value;
string msg;
public:
NegativeValueException(int v) : value(v),
msg("Negative value: " + to_string(v)) {}
const char* what() const noexcept override { return msg.c_str(); }
int getValue() const { return value; }
};
Ex6:
template<typename T, size_t N>
class Stack {
T data[N];
size_t top = 0;
public:
void push(const T& val) {
if (top >= N) throw overflow_error("Stack full");
data[top++] = val;
}
T pop() {
if (top == 0) throw underflow_error("Stack empty");
return data[--top];
}
};
Ex7:
class ResourceGuard {
public:
ResourceGuard() { cout << "Resource acquired" << endl; }
~ResourceGuard() { cout << "Resource released" << endl; }
};
void test() {
ResourceGuard rg;
throw runtime_error("Error");
// rg.~ResourceGuard() still called!
}
*/