cpp
exercises
exercises.cpp⚙️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++];
}
*/