cpp

exercises

exercises.cpp⚙️
/**
 * Dynamic Memory in C++ - Exercises
 * 
 * Practice problems for understanding dynamic memory allocation.
 * 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 <cstring>

using namespace std;

// ============================================================
// Exercise 1: Allocate and Delete Single Value ⭐
// ============================================================
/**
 * Allocate an integer, use it, and delete it.
 */
void exercise1() {
    // TODO: Allocate an integer with value 42
    int* ptr = nullptr;  // Fix this
    
    // TODO: Print the value
    cout << "Value: " << 0 << " (expected: 42)" << endl;  // Fix this
    
    // TODO: Delete the memory and set to nullptr
    
}

// ============================================================
// Exercise 2: Allocate Object ⭐
// ============================================================
/**
 * Allocate a string object dynamically.
 */
void exercise2() {
    // TODO: Allocate a string with value "Hello, Dynamic World!"
    string* strPtr = nullptr;  // Fix this
    
    // TODO: Print the string
    cout << "String: " << "" << " (expected: Hello, Dynamic World!)" << endl;  // Fix
    
    // TODO: Delete and set to nullptr
    
}

// ============================================================
// Exercise 3: Dynamic Array ⭐⭐
// ============================================================
/**
 * Create a dynamic array, fill it, and delete it.
 */
void exercise3() {
    int size = 5;
    
    // TODO: Allocate an array of 'size' integers
    int* arr = nullptr;  // Fix this
    
    // TODO: Fill array with values 10, 20, 30, 40, 50
    
    cout << "Array: ";
    for (int i = 0; i < size; i++) {
        cout << 0 << " ";  // Fix: print arr[i]
    }
    cout << "(expected: 10 20 30 40 50)" << endl;
    
    // TODO: Delete array properly
    
}

// ============================================================
// Exercise 4: Zero-Initialized Array ⭐⭐
// ============================================================
/**
 * Create a zero-initialized dynamic array.
 */
void exercise4() {
    int size = 5;
    
    // TODO: Allocate a zero-initialized array of 'size' integers
    // Hint: new int[size]()
    int* arr = nullptr;  // Fix this
    
    cout << "Zero-initialized array: ";
    for (int i = 0; i < size; i++) {
        cout << 0 << " ";  // Fix: print arr[i]
    }
    cout << "(expected: 0 0 0 0 0)" << endl;
    
    // TODO: Delete array properly
    
}

// ============================================================
// Exercise 5: Sum Dynamic Array ⭐⭐
// ============================================================
/**
 * Create a function that allocates an array and returns its sum.
 */
int sumDynamicArray(int size) {
    // TODO: Allocate array of 'size' integers
    // TODO: Fill with values 1 to size
    // TODO: Calculate sum
    // TODO: Delete array
    // TODO: Return sum
    return 0;
}

void exercise5() {
    int sum = sumDynamicArray(10);
    cout << "Sum of 1 to 10: " << sum << " (expected: 55)" << endl;
}

// ============================================================
// Exercise 6: Double Pointer Allocation ⭐⭐
// ============================================================
/**
 * Allocate memory through a double pointer.
 */
void allocateInt(int** pptr, int value) {
    // TODO: Allocate a new int with 'value' and store in *pptr
    
}

void exercise6() {
    int* ptr = nullptr;
    
    allocateInt(&ptr, 99);
    
    if (ptr != nullptr) {
        cout << "Allocated value: " << *ptr << " (expected: 99)" << endl;
        
        // TODO: Delete the memory
        
        ptr = nullptr;
    }
}

// ============================================================
// Exercise 7: Resize Array ⭐⭐⭐
// ============================================================
/**
 * "Resize" a dynamic array (create new, copy, delete old).
 */
int* resizeArray(int* oldArr, int oldSize, int newSize) {
    // TODO: Allocate new array of newSize
    // TODO: Copy elements (min of oldSize, newSize)
    // TODO: Delete old array
    // TODO: Return new array
    return nullptr;
}

void exercise7() {
    int* arr = new int[3]{10, 20, 30};
    
    cout << "Original (size 3): ";
    for (int i = 0; i < 3; i++) cout << arr[i] << " ";
    cout << endl;
    
    arr = resizeArray(arr, 3, 5);
    
    // Fill new slots
    arr[3] = 40;
    arr[4] = 50;
    
    cout << "Resized (size 5): ";
    for (int i = 0; i < 5; i++) cout << arr[i] << " ";
    cout << endl;
    cout << "(expected: 10 20 30 40 50)" << endl;
    
    delete[] arr;
}

// ============================================================
// Exercise 8: 2D Array ⭐⭐⭐
// ============================================================
/**
 * Allocate and deallocate a 2D array.
 */
int** create2DArray(int rows, int cols) {
    // TODO: Allocate array of pointers
    // TODO: Allocate each row
    // TODO: Return the 2D array
    return nullptr;
}

void delete2DArray(int** matrix, int rows) {
    // TODO: Delete each row
    // TODO: Delete array of pointers
    
}

void exercise8() {
    int rows = 3, cols = 4;
    
    int** matrix = create2DArray(rows, cols);
    
    if (matrix != nullptr) {
        // Fill with values
        int val = 1;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                matrix[i][j] = val++;
            }
        }
        
        // Print
        cout << "2D Array:" << endl;
        for (int i = 0; i < rows; i++) {
            cout << "  ";
            for (int j = 0; j < cols; j++) {
                cout << matrix[i][j] << "\t";
            }
            cout << endl;
        }
        
        delete2DArray(matrix, rows);
        cout << "2D Array deallocated" << endl;
    }
}

// ============================================================
// Exercise 9: Dynamic String Copy ⭐⭐⭐
// ============================================================
/**
 * Create a function that duplicates a C-string dynamically.
 */
char* duplicateString(const char* original) {
    // TODO: Allocate memory for copy (strlen + 1 for null terminator)
    // TODO: Copy the string
    // TODO: Return the copy
    return nullptr;
}

void exercise9() {
    const char* original = "Hello, World!";
    
    char* copy = duplicateString(original);
    
    if (copy != nullptr) {
        cout << "Original: " << original << endl;
        cout << "Copy: " << copy << endl;
        cout << "Are they equal? " << (strcmp(original, copy) == 0 ? "Yes" : "No") << endl;
        
        delete[] copy;
    }
}

// ============================================================
// Exercise 10: RAII Integer Wrapper ⭐⭐⭐
// ============================================================
/**
 * Create an RAII class that wraps a dynamic integer.
 */
class DynamicInt {
private:
    int* ptr;
    
public:
    // TODO: Constructor - allocate and initialize
    DynamicInt(int value) : ptr(nullptr) {
        // Allocate and set value
    }
    
    // TODO: Destructor - deallocate
    ~DynamicInt() {
        // Delete ptr
    }
    
    // TODO: Get value
    int getValue() const {
        return 0;  // Fix this
    }
    
    // TODO: Set value
    void setValue(int value) {
        // Set *ptr to value
    }
    
    // Disable copying
    DynamicInt(const DynamicInt&) = delete;
    DynamicInt& operator=(const DynamicInt&) = delete;
};

void exercise10() {
    cout << "Creating DynamicInt:" << endl;
    {
        DynamicInt di(42);
        cout << "  Value: " << di.getValue() << " (expected: 42)" << endl;
        
        di.setValue(100);
        cout << "  After setValue(100): " << di.getValue() << " (expected: 100)" << endl;
        
        cout << "  Leaving scope..." << endl;
    }
    cout << "  After scope - should see destruction" << endl;
}

// ============================================================
// Exercise 11: RAII Array Wrapper ⭐⭐⭐
// ============================================================
/**
 * Create an RAII class that wraps a dynamic array.
 */
class DynamicArray {
private:
    int* data;
    size_t size;
    
public:
    // TODO: Constructor - allocate array of given size
    explicit DynamicArray(size_t n) : data(nullptr), size(n) {
        
    }
    
    // TODO: Destructor - deallocate
    ~DynamicArray() {
        
    }
    
    // TODO: Element access with bounds (optional)
    int& operator[](size_t index) {
        return data[index];
    }
    
    size_t getSize() const { return size; }
    
    // Disable copying
    DynamicArray(const DynamicArray&) = delete;
    DynamicArray& operator=(const DynamicArray&) = delete;
};

void exercise11() {
    cout << "Creating DynamicArray:" << endl;
    {
        DynamicArray arr(5);
        
        for (size_t i = 0; i < arr.getSize(); i++) {
            arr[i] = (i + 1) * 10;
        }
        
        cout << "  Array: ";
        for (size_t i = 0; i < arr.getSize(); i++) {
            cout << arr[i] << " ";
        }
        cout << "(expected: 10 20 30 40 50)" << endl;
        
        cout << "  Leaving scope..." << endl;
    }
    cout << "  After scope - should be deallocated" << endl;
}

// ============================================================
// Exercise 12: Nothrow Allocation ⭐⭐
// ============================================================
/**
 * Use nothrow to handle allocation failure gracefully.
 */
void exercise12() {
    // TODO: Try to allocate a small array using nothrow
    // TODO: Check if allocation succeeded
    // TODO: If succeeded, use and delete; if failed, print message
    
    int* arr = nullptr;  // Use new(nothrow)
    
    if (arr != nullptr) {
        cout << "Allocation succeeded" << endl;
        arr[0] = 42;
        cout << "First element: " << arr[0] << endl;
        delete[] arr;
    } else {
        cout << "Allocation failed" << endl;
    }
}

// ============================================================
// Exercise 13: Factory Function ⭐⭐⭐
// ============================================================
/**
 * Create a factory function that returns a dynamically allocated object.
 */
struct Rectangle {
    int width;
    int height;
    
    Rectangle(int w, int h) : width(w), height(h) {}
    
    int area() const { return width * height; }
};

Rectangle* createRectangle(int width, int height) {
    // TODO: Allocate and return a new Rectangle
    return nullptr;
}

void exercise13() {
    Rectangle* rect = createRectangle(5, 3);
    
    if (rect != nullptr) {
        cout << "Rectangle: " << rect->width << " x " << rect->height << endl;
        cout << "Area: " << rect->area() << " (expected: 15)" << endl;
        
        // TODO: Delete the rectangle
        
    }
}

// ============================================================
// Exercise 14: Linked List Node ⭐⭐⭐
// ============================================================
/**
 * Practice dynamic allocation with a simple linked list.
 */
struct Node {
    int data;
    Node* next;
    
    Node(int d) : data(d), next(nullptr) {}
};

void exercise14() {
    // TODO: Create a linked list: 10 -> 20 -> 30
    Node* head = nullptr;  // Start building here
    
    // TODO: Traverse and print
    cout << "Linked list: ";
    Node* current = head;
    while (current != nullptr) {
        cout << current->data << " -> ";
        current = current->next;
    }
    cout << "nullptr" << endl;
    cout << "(expected: 10 -> 20 -> 30 -> nullptr)" << endl;
    
    // TODO: Delete all nodes
    
}

// ============================================================
// Exercise 15: Memory Pool Simulation ⭐⭐⭐
// ============================================================
/**
 * Simulate a simple memory pool (allocate multiple, delete all at once).
 */
class IntPool {
private:
    int** allocations;
    size_t count;
    size_t capacity;
    
public:
    IntPool(size_t maxAllocations) : count(0), capacity(maxAllocations) {
        // TODO: Allocate array of pointers
        allocations = nullptr;  // Fix this
    }
    
    ~IntPool() {
        // TODO: Delete all stored allocations
        // TODO: Delete the allocations array
        
    }
    
    int* allocate(int value) {
        // TODO: Allocate new int, store pointer, return it
        return nullptr;
    }
    
    size_t getCount() const { return count; }
};

void exercise15() {
    cout << "Creating IntPool:" << endl;
    {
        IntPool pool(10);
        
        int* a = pool.allocate(10);
        int* b = pool.allocate(20);
        int* c = pool.allocate(30);
        
        if (a && b && c) {
            cout << "  Allocated: " << *a << ", " << *b << ", " << *c << endl;
            cout << "  Count: " << pool.getCount() << " (expected: 3)" << endl;
        }
        
        cout << "  Leaving scope (pool destructor will free all)..." << endl;
    }
    cout << "  After scope - all memory freed" << endl;
}

// ============================================================
// TEST RUNNER
// ============================================================

int main() {
    cout << "╔════════════════════════════════════════════════════════════╗" << endl;
    cout << "║           DYNAMIC MEMORY - EXERCISES                       ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════╝" << endl;
    
    cout << "\n=== Exercise 1: Allocate Single Value ===" << endl;
    exercise1();
    
    cout << "\n=== Exercise 2: Allocate Object ===" << endl;
    exercise2();
    
    cout << "\n=== Exercise 3: Dynamic Array ===" << endl;
    exercise3();
    
    cout << "\n=== Exercise 4: Zero-Initialized Array ===" << endl;
    exercise4();
    
    cout << "\n=== Exercise 5: Sum Dynamic Array ===" << endl;
    exercise5();
    
    cout << "\n=== Exercise 6: Double Pointer Allocation ===" << endl;
    exercise6();
    
    cout << "\n=== Exercise 7: Resize Array ===" << endl;
    exercise7();
    
    cout << "\n=== Exercise 8: 2D Array ===" << endl;
    exercise8();
    
    cout << "\n=== Exercise 9: Dynamic String Copy ===" << endl;
    exercise9();
    
    cout << "\n=== Exercise 10: RAII Integer Wrapper ===" << endl;
    exercise10();
    
    cout << "\n=== Exercise 11: RAII Array Wrapper ===" << endl;
    exercise11();
    
    cout << "\n=== Exercise 12: Nothrow Allocation ===" << endl;
    exercise12();
    
    cout << "\n=== Exercise 13: Factory Function ===" << endl;
    exercise13();
    
    cout << "\n=== Exercise 14: Linked List Node ===" << endl;
    exercise14();
    
    cout << "\n=== Exercise 15: Memory Pool ===" << endl;
    exercise15();
    
    cout << "\n╔════════════════════════════════════════════════════════════╗" << endl;
    cout << "║         Complete the TODO sections and re-run!             ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════╝" << endl;
    
    return 0;
}

// ============================================================
// ANSWER KEY
// ============================================================
/*
// Exercise 1
int* ptr = new int(42);
cout << "Value: " << *ptr << endl;
delete ptr;
ptr = nullptr;

// Exercise 2
string* strPtr = new string("Hello, Dynamic World!");
cout << "String: " << *strPtr << endl;
delete strPtr;
strPtr = nullptr;

// Exercise 3
int* arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = (i + 1) * 10;
for (int i = 0; i < size; i++) cout << arr[i] << " ";
delete[] arr;

// Exercise 4
int* arr = new int[size]();
for (int i = 0; i < size; i++) cout << arr[i] << " ";
delete[] arr;

// Exercise 5
int sumDynamicArray(int size) {
    int* arr = new int[size];
    for (int i = 0; i < size; i++) arr[i] = i + 1;
    int sum = 0;
    for (int i = 0; i < size; i++) sum += arr[i];
    delete[] arr;
    return sum;
}

// Exercise 6
void allocateInt(int** pptr, int value) {
    *pptr = new int(value);
}
delete ptr;

// Exercise 7
int* resizeArray(int* oldArr, int oldSize, int newSize) {
    int* newArr = new int[newSize]();
    int copySize = (oldSize < newSize) ? oldSize : newSize;
    for (int i = 0; i < copySize; i++) newArr[i] = oldArr[i];
    delete[] oldArr;
    return newArr;
}

// Exercise 8
int** create2DArray(int rows, int cols) {
    int** matrix = new int*[rows];
    for (int i = 0; i < rows; i++) matrix[i] = new int[cols];
    return matrix;
}
void delete2DArray(int** matrix, int rows) {
    for (int i = 0; i < rows; i++) delete[] matrix[i];
    delete[] matrix;
}

// Exercise 9
char* duplicateString(const char* original) {
    char* copy = new char[strlen(original) + 1];
    strcpy(copy, original);
    return copy;
}

// Exercise 10
DynamicInt(int value) : ptr(new int(value)) {}
~DynamicInt() { delete ptr; }
int getValue() const { return *ptr; }
void setValue(int value) { *ptr = value; }

// Exercise 11
DynamicArray(size_t n) : data(new int[n]()), size(n) {}
~DynamicArray() { delete[] data; }

// Exercise 12
int* arr = new(nothrow) int[10];

// Exercise 13
Rectangle* createRectangle(int width, int height) {
    return new Rectangle(width, height);
}
delete rect;

// Exercise 14
Node* head = new Node(10);
head->next = new Node(20);
head->next->next = new Node(30);
// Delete:
while (head != nullptr) {
    Node* temp = head;
    head = head->next;
    delete temp;
}

// Exercise 15
IntPool(size_t maxAllocations) : count(0), capacity(maxAllocations) {
    allocations = new int*[capacity];
}
~IntPool() {
    for (size_t i = 0; i < count; i++) delete allocations[i];
    delete[] allocations;
}
int* allocate(int value) {
    if (count >= capacity) return nullptr;
    allocations[count] = new int(value);
    return allocations[count++];
}
*/
Exercises - C++ Tutorial | DeepML