cpp
exercises
exercises.cpp⚙️cpp
/**
* Classes in C++ - Exercises
*
* Practice problems for understanding classes and OOP basics.
* Each exercise includes TODO sections to complete.
*
* Compile: g++ -std=c++17 -Wall -Wextra exercises.cpp -o exercises
* Run: ./exercises
*/
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
// ============================================================
// Exercise 1: Create a Simple Class ⭐
// ============================================================
/**
* Create a Rectangle class with width and height,
* and methods to calculate area and perimeter.
*/
// TODO: Define the Rectangle class here
class Rectangle {
// TODO: Add private members: width, height (both double)
public:
// TODO: Add constructor that takes width and height
// TODO: Add getArea() method
// TODO: Add getPerimeter() method
// TODO: Add print() method to display dimensions
};
void exercise1() {
// TODO: Uncomment when Rectangle is implemented
/*
Rectangle r(5.0, 3.0);
r.print();
cout << "Area: " << r.getArea() << " (expected: 15)" << endl;
cout << "Perimeter: " << r.getPerimeter() << " (expected: 16)" << endl;
*/
cout << "(Implement Rectangle class to see results)" << endl;
}
// ============================================================
// Exercise 2: Constructors and Destructors ⭐⭐
// ============================================================
/**
* Create a Message class that prints when it's created/destroyed.
*/
class Message {
private:
string text;
int id;
static int nextId;
public:
// TODO: Constructor that takes text, assigns unique id
// Should print: "Message X created: <text>"
Message(const string& t) : text(t), id(0) {
// Fix this
}
// TODO: Destructor
// Should print: "Message X destroyed: <text>"
~Message() {
// Add code
}
void display() const {
cout << "[" << id << "] " << text << endl;
}
};
int Message::nextId = 1;
void exercise2() {
cout << "Creating messages:" << endl;
{
Message m1("Hello");
Message m2("World");
m1.display();
m2.display();
cout << "Leaving scope:" << endl;
}
cout << "After scope" << endl;
}
// ============================================================
// Exercise 3: Copy Constructor ⭐⭐
// ============================================================
/**
* Implement a proper copy constructor for a class with dynamic memory.
*/
class IntArray {
private:
int* data;
int size;
public:
IntArray(int s) : size(s) {
data = new int[size];
for (int i = 0; i < size; i++) {
data[i] = 0;
}
}
// TODO: Implement copy constructor (deep copy)
IntArray(const IntArray& other) : size(0), data(nullptr) {
// Deep copy: allocate new array and copy values
}
~IntArray() {
delete[] data;
}
void set(int index, int value) {
if (index >= 0 && index < size) {
data[index] = value;
}
}
int get(int index) const {
if (index >= 0 && index < size) {
return data[index];
}
return 0;
}
int getSize() const { return size; }
void print() const {
cout << "[";
for (int i = 0; i < size; i++) {
cout << data[i];
if (i < size - 1) cout << ", ";
}
cout << "]" << endl;
}
};
void exercise3() {
IntArray arr1(5);
arr1.set(0, 10);
arr1.set(1, 20);
arr1.set(2, 30);
cout << "Original array: ";
arr1.print();
// Copy
IntArray arr2 = arr1;
cout << "Copied array: ";
arr2.print();
// Modify original
arr1.set(0, 999);
cout << "\nAfter modifying original:" << endl;
cout << "Original: ";
arr1.print();
cout << "Copy: ";
arr2.print();
cout << "(Copy should be unchanged if deep copy works)" << endl;
}
// ============================================================
// Exercise 4: Static Members ⭐⭐
// ============================================================
/**
* Create a class that tracks how many instances exist.
*/
class Counter {
private:
int value;
// TODO: Add static member to count instances
public:
Counter(int v = 0) : value(v) {
// TODO: Increment instance count
}
~Counter() {
// TODO: Decrement instance count
}
// TODO: Add static method getInstanceCount()
int getValue() const { return value; }
};
// TODO: Define static member outside class
void exercise4() {
cout << "Initial count: " << 0 << " (expected: 0)" << endl; // Fix
{
Counter c1(10);
Counter c2(20);
cout << "After creating 2: " << 0 << " (expected: 2)" << endl; // Fix
Counter c3 = c1;
cout << "After copying: " << 0 << " (expected: 3)" << endl; // Fix
}
cout << "After scope: " << 0 << " (expected: 0)" << endl; // Fix
}
// ============================================================
// Exercise 5: Method Chaining ⭐⭐
// ============================================================
/**
* Implement a StringBuilder class with method chaining.
*/
class StringBuilder {
private:
string content;
public:
StringBuilder() : content("") {}
// TODO: Implement append() that returns *this
StringBuilder& append(const string& str) {
// Add str to content
return *this; // Fix if needed
}
// TODO: Implement appendLine() that appends with newline
StringBuilder& appendLine(const string& str) {
return *this; // Fix
}
// TODO: Implement clear()
StringBuilder& clear() {
return *this; // Fix
}
string toString() const { return content; }
int length() const { return content.length(); }
};
void exercise5() {
StringBuilder sb;
sb.append("Hello")
.append(" ")
.append("World")
.appendLine("!")
.append("This is a new line.");
cout << "Result:" << endl;
cout << sb.toString() << endl;
cout << "Length: " << sb.length() << endl;
}
// ============================================================
// Exercise 6: Const Correctness ⭐⭐
// ============================================================
/**
* Fix the const-correctness issues in this class.
*/
class Temperature {
private:
double celsius;
public:
Temperature(double c) : celsius(c) {}
// TODO: Fix these methods - add 'const' where appropriate
double getCelsius() { return celsius; } // Should be const?
double getFahrenheit() { return celsius * 9.0 / 5.0 + 32; } // Should be const?
double getKelvin() { return celsius + 273.15; } // Should be const?
void setCelsius(double c) { celsius = c; } // Should be const?
void display() { // Should be const?
cout << celsius << "°C = " << getFahrenheit() << "°F = " << getKelvin() << "K" << endl;
}
};
void exercise6() {
Temperature t(25.0);
t.display();
// This should work with proper const methods:
const Temperature freezing(0.0);
// TODO: Uncomment these when const-correctness is fixed
// cout << "Freezing in F: " << freezing.getFahrenheit() << endl;
// freezing.display();
}
// ============================================================
// Exercise 7: Bank Account Class ⭐⭐⭐
// ============================================================
/**
* Create a complete BankAccount class.
*/
class BankAccount {
private:
string accountNumber;
string ownerName;
double balance;
// TODO: Add static member for next account number
public:
// TODO: Constructor - auto-generate account number
BankAccount(const string& owner, double initial = 0.0)
: accountNumber("000000"), ownerName(owner), balance(initial) {
// Generate account number like "ACC001", "ACC002", etc.
}
// TODO: Implement deposit (validate positive amount)
bool deposit(double amount) {
return false; // Fix
}
// TODO: Implement withdraw (validate sufficient balance)
bool withdraw(double amount) {
return false; // Fix
}
// TODO: Implement transfer to another account
bool transfer(BankAccount& other, double amount) {
return false; // Fix
}
// Getters
string getAccountNumber() const { return accountNumber; }
string getOwnerName() const { return ownerName; }
double getBalance() const { return balance; }
void display() const {
cout << "Account: " << accountNumber << endl;
cout << "Owner: " << ownerName << endl;
cout << "Balance: $" << balance << endl;
}
};
// TODO: Initialize static member
void exercise7() {
BankAccount acc1("Alice", 1000.0);
BankAccount acc2("Bob", 500.0);
cout << "Initial state:" << endl;
acc1.display();
cout << endl;
acc2.display();
cout << "\nAlice deposits $200:" << endl;
acc1.deposit(200);
cout << "Alice's balance: $" << acc1.getBalance() << endl;
cout << "\nBob withdraws $100:" << endl;
acc2.withdraw(100);
cout << "Bob's balance: $" << acc2.getBalance() << endl;
cout << "\nAlice transfers $300 to Bob:" << endl;
acc1.transfer(acc2, 300);
cout << "Alice's balance: $" << acc1.getBalance() << endl;
cout << "Bob's balance: $" << acc2.getBalance() << endl;
}
// ============================================================
// Exercise 8: Circle Class ⭐⭐
// ============================================================
/**
* Create a Circle class with proper encapsulation.
*/
class Circle {
// TODO: Add private radius member
public:
// TODO: Static constant for PI
// TODO: Constructor with default radius of 1.0
// TODO: Getter and setter for radius (validate positive)
// TODO: getArea() method
// TODO: getCircumference() method
// TODO: scale() method that multiplies radius by factor
};
void exercise8() {
// TODO: Uncomment when Circle is implemented
/*
Circle c1; // Default radius
cout << "Default circle area: " << c1.getArea() << endl;
Circle c2(5.0);
cout << "Circle (r=5) area: " << c2.getArea() << endl;
cout << "Circle (r=5) circumference: " << c2.getCircumference() << endl;
c2.scale(2.0);
cout << "After scaling by 2, area: " << c2.getArea() << endl;
*/
cout << "(Implement Circle class to see results)" << endl;
}
// ============================================================
// Exercise 9: Date Class ⭐⭐⭐
// ============================================================
/**
* Create a Date class with validation.
*/
class Date {
private:
int day, month, year;
// TODO: Static method to check if year is leap year
static bool isLeapYear(int y) {
return false; // Fix
}
// TODO: Static method to get days in month
static int daysInMonth(int m, int y) {
return 30; // Fix
}
// TODO: Method to validate date
bool isValid() const {
return true; // Fix
}
public:
Date(int d, int m, int y) : day(d), month(m), year(y) {
if (!isValid()) {
cout << "Invalid date! Setting to 1/1/2000" << endl;
day = 1; month = 1; year = 2000;
}
}
void display() const {
cout << day << "/" << month << "/" << year << endl;
}
// TODO: Implement addDays() method
void addDays(int days) {
// Add 'days' to the date, handling month/year overflow
}
};
void exercise9() {
Date d1(15, 6, 2024);
cout << "Date 1: ";
d1.display();
Date d2(31, 2, 2024); // Invalid - Feb doesn't have 31 days
cout << "Date 2: ";
d2.display();
Date d3(29, 2, 2024); // Valid - 2024 is leap year
cout << "Date 3: ";
d3.display();
}
// ============================================================
// Exercise 10: Student Class ⭐⭐⭐
// ============================================================
/**
* Create a Student class with grades management.
*/
class Student {
private:
string name;
int id;
double grades[10]; // Fixed size for simplicity
int gradeCount;
static int nextId;
public:
// TODO: Constructor
Student(const string& n) : name(n), id(0), gradeCount(0) {
// Initialize grades array
}
// TODO: Add a grade (validate 0-100 range)
bool addGrade(double grade) {
return false; // Fix
}
// TODO: Calculate average
double getAverage() const {
return 0.0; // Fix
}
// TODO: Get letter grade based on average
char getLetterGrade() const {
// A: 90+, B: 80-89, C: 70-79, D: 60-69, F: <60
return 'F'; // Fix
}
void display() const {
cout << "Student: " << name << " (ID: " << id << ")" << endl;
cout << "Grades: ";
for (int i = 0; i < gradeCount; i++) {
cout << grades[i] << " ";
}
cout << endl;
cout << "Average: " << getAverage() << " (" << getLetterGrade() << ")" << endl;
}
};
int Student::nextId = 1000;
void exercise10() {
Student s("John Doe");
s.addGrade(85);
s.addGrade(92);
s.addGrade(78);
s.addGrade(88);
s.addGrade(95);
s.display();
}
// ============================================================
// Exercise 11: Time Class ⭐⭐
// ============================================================
/**
* Create a Time class with hours, minutes, seconds.
*/
class Time {
private:
int hours, minutes, seconds;
// Helper to normalize time
void normalize() {
// TODO: Handle overflow (e.g., 90 seconds -> 1 min 30 sec)
}
public:
Time(int h = 0, int m = 0, int s = 0)
: hours(h), minutes(m), seconds(s) {
normalize();
}
// TODO: Add seconds to time
void addSeconds(int s) {
// Add seconds and normalize
}
// TODO: Add minutes to time
void addMinutes(int m) {
// Add minutes and normalize
}
// TODO: Convert to total seconds
int toSeconds() const {
return 0; // Fix
}
void display() const {
cout << (hours < 10 ? "0" : "") << hours << ":"
<< (minutes < 10 ? "0" : "") << minutes << ":"
<< (seconds < 10 ? "0" : "") << seconds << endl;
}
};
void exercise11() {
Time t(1, 30, 45);
cout << "Initial time: ";
t.display();
t.addSeconds(30);
cout << "After adding 30 seconds: ";
t.display();
t.addMinutes(45);
cout << "After adding 45 minutes: ";
t.display();
cout << "Total seconds: " << t.toSeconds() << endl;
}
// ============================================================
// Exercise 12: Car Class ⭐⭐
// ============================================================
/**
* Create a Car class with fuel management.
*/
class Car {
// TODO: Add private members: make, model, fuelLevel, tankCapacity, mpg
public:
// TODO: Constructor
// TODO: refuel(gallons) - add fuel, don't exceed tank capacity
// TODO: drive(miles) - consume fuel, return actual miles driven
// TODO: getFuelLevel() and getRange() methods
// TODO: display() method
};
void exercise12() {
// TODO: Uncomment when Car is implemented
/*
Car car("Toyota", "Camry", 15.0, 30.0); // 15 gal tank, 30 mpg
car.display();
car.refuel(10.0); // Add 10 gallons
cout << "After refueling: " << car.getFuelLevel() << " gallons" << endl;
cout << "Range: " << car.getRange() << " miles" << endl;
double driven = car.drive(150); // Try to drive 150 miles
cout << "Actually drove: " << driven << " miles" << endl;
cout << "Fuel remaining: " << car.getFuelLevel() << " gallons" << endl;
*/
cout << "(Implement Car class to see results)" << endl;
}
// ============================================================
// TEST RUNNER
// ============================================================
int main() {
cout << "╔════════════════════════════════════════════════════════════╗" << endl;
cout << "║ CLASSES - EXERCISES ║" << endl;
cout << "╚════════════════════════════════════════════════════════════╝" << endl;
cout << "\n=== Exercise 1: Simple Class ===" << endl;
exercise1();
cout << "\n=== Exercise 2: Constructors/Destructors ===" << endl;
exercise2();
cout << "\n=== Exercise 3: Copy Constructor ===" << endl;
exercise3();
cout << "\n=== Exercise 4: Static Members ===" << endl;
exercise4();
cout << "\n=== Exercise 5: Method Chaining ===" << endl;
exercise5();
cout << "\n=== Exercise 6: Const Correctness ===" << endl;
exercise6();
cout << "\n=== Exercise 7: Bank Account ===" << endl;
exercise7();
cout << "\n=== Exercise 8: Circle Class ===" << endl;
exercise8();
cout << "\n=== Exercise 9: Date Class ===" << endl;
exercise9();
cout << "\n=== Exercise 10: Student Class ===" << endl;
exercise10();
cout << "\n=== Exercise 11: Time Class ===" << endl;
exercise11();
cout << "\n=== Exercise 12: Car Class ===" << endl;
exercise12();
cout << "\n╔════════════════════════════════════════════════════════════╗" << endl;
cout << "║ Complete the TODO sections and re-run! ║" << endl;
cout << "╚════════════════════════════════════════════════════════════╝" << endl;
return 0;
}
// ============================================================
// ANSWER KEY
// ============================================================
/*
// Exercise 1: Rectangle
class Rectangle {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double getArea() const { return width * height; }
double getPerimeter() const { return 2 * (width + height); }
void print() const { cout << "Rectangle: " << width << " x " << height << endl; }
};
// Exercise 2: Message
Message(const string& t) : text(t), id(nextId++) {
cout << "Message " << id << " created: " << text << endl;
}
~Message() {
cout << "Message " << id << " destroyed: " << text << endl;
}
// Exercise 3: Copy Constructor
IntArray(const IntArray& other) : size(other.size) {
data = new int[size];
for (int i = 0; i < size; i++) {
data[i] = other.data[i];
}
}
// Exercise 4: Static Members
private:
static int instanceCount;
Counter(int v = 0) : value(v) { instanceCount++; }
~Counter() { instanceCount--; }
static int getInstanceCount() { return instanceCount; }
int Counter::instanceCount = 0;
// Exercise 5: StringBuilder
StringBuilder& append(const string& str) { content += str; return *this; }
StringBuilder& appendLine(const string& str) { content += str + "\n"; return *this; }
StringBuilder& clear() { content = ""; return *this; }
// Exercise 6: Add 'const' to getCelsius, getFahrenheit, getKelvin, display
// Exercise 7: BankAccount
static int nextAccNum;
BankAccount(...) : accountNumber("ACC" + to_string(nextAccNum++)), ...
bool deposit(double amount) {
if (amount > 0) { balance += amount; return true; }
return false;
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) { balance -= amount; return true; }
return false;
}
bool transfer(BankAccount& other, double amount) {
if (withdraw(amount)) { other.deposit(amount); return true; }
return false;
}
// Exercise 8: Circle
private:
double radius;
public:
static constexpr double PI = 3.14159265359;
Circle(double r = 1.0) : radius(r > 0 ? r : 1.0) {}
double getRadius() const { return radius; }
void setRadius(double r) { if (r > 0) radius = r; }
double getArea() const { return PI * radius * radius; }
double getCircumference() const { return 2 * PI * radius; }
void scale(double factor) { if (factor > 0) radius *= factor; }
// Exercise 9: Date
static bool isLeapYear(int y) {
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
static int daysInMonth(int m, int y) {
int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (m == 2 && isLeapYear(y)) return 29;
return days[m-1];
}
bool isValid() const {
if (month < 1 || month > 12) return false;
if (day < 1 || day > daysInMonth(month, year)) return false;
return true;
}
// Exercise 10: Student
Student(const string& n) : name(n), id(nextId++), gradeCount(0) {
for (int i = 0; i < 10; i++) grades[i] = 0;
}
bool addGrade(double grade) {
if (gradeCount < 10 && grade >= 0 && grade <= 100) {
grades[gradeCount++] = grade;
return true;
}
return false;
}
double getAverage() const {
if (gradeCount == 0) return 0;
double sum = 0;
for (int i = 0; i < gradeCount; i++) sum += grades[i];
return sum / gradeCount;
}
char getLetterGrade() const {
double avg = getAverage();
if (avg >= 90) return 'A';
if (avg >= 80) return 'B';
if (avg >= 70) return 'C';
if (avg >= 60) return 'D';
return 'F';
}
// Exercise 11: Time
void normalize() {
minutes += seconds / 60;
seconds %= 60;
hours += minutes / 60;
minutes %= 60;
}
void addSeconds(int s) { seconds += s; normalize(); }
void addMinutes(int m) { minutes += m; normalize(); }
int toSeconds() const { return hours * 3600 + minutes * 60 + seconds; }
// Exercise 12: Car
class Car {
string make, model;
double fuelLevel, tankCapacity, mpg;
public:
Car(string mk, string md, double tank, double m)
: make(mk), model(md), fuelLevel(0), tankCapacity(tank), mpg(m) {}
void refuel(double gallons) {
fuelLevel = min(fuelLevel + gallons, tankCapacity);
}
double drive(double miles) {
double fuelNeeded = miles / mpg;
if (fuelNeeded > fuelLevel) {
double actualMiles = fuelLevel * mpg;
fuelLevel = 0;
return actualMiles;
}
fuelLevel -= fuelNeeded;
return miles;
}
double getFuelLevel() const { return fuelLevel; }
double getRange() const { return fuelLevel * mpg; }
};
*/