Skip to content

💪 Exercises — Bài tập thực hành

Lý thuyết không đủ — bạn cần code thực tế. Hoàn thành 3 bài tập dưới đây để củng cố kiến thức về Memory, Pointers, và I/O.

🏆 Challenge 1: Swap Two Variables Using Pointers

Yêu cầu

Viết hàm swapPointers nhận vào hai con trỏ và hoán đổi giá trị tại hai địa chỉ đó.

cpp
#include <iostream>

void swapPointers(int* a, int* b) {
    // TODO: Implement this function
}

int main() {
    int x = 10, y = 20;
    
    std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
    
    swapPointers(&x, &y);
    
    std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
    // Expected: x = 20, y = 10
    
    return 0;
}
💡 Gợi ý
  • Bạn cần dereference pointer để truy cập giá trị
  • Dùng biến tạm để lưu giá trị trước khi ghi đè
Lời giải
cpp
#include <iostream>

void swapPointers(int* a, int* b) {
    int temp = *a;  // Lưu giá trị tại địa chỉ a
    *a = *b;        // Gán giá trị tại b cho vị trí a
    *b = temp;      // Gán temp cho vị trí b
}

int main() {
    int x = 10, y = 20;
    
    std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
    
    swapPointers(&x, &y);
    
    std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
    
    return 0;
}

Output:

Before swap: x = 10, y = 20
After swap: x = 20, y = 10

Bonus — Version với References (cleaner):

cpp
void swapRef(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

// Usage: swapRef(x, y);  // Không cần &

🏆 Challenge 2: Array Traversal Using Pointer Arithmetic

Yêu cầu

Cho một mảng số nguyên, in tất cả phần tử sử dụng pointer arithmetic (không dùng array indexing arr[i]).

cpp
#include <iostream>

void printArrayWithPointer(int* arr, int size) {
    // TODO: Dùng pointer arithmetic để in từng phần tử
    // KHÔNG được dùng arr[i]!
}

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    std::cout << "Array elements: ";
    printArrayWithPointer(numbers, size);
    std::cout << std::endl;
    
    // Expected output: 10 20 30 40 50
    
    return 0;
}
💡 Gợi ý
  • *(arr + i) tương đương arr[i]
  • Hoặc dùng ptr++ để di chuyển pointer qua từng phần tử
Lời giải

*Cách 1: Dùng (arr + i)

cpp
#include <iostream>

void printArrayWithPointer(int* arr, int size) {
    for (int i = 0; i < size; ++i) {
        std::cout << *(arr + i) << " ";
    }
}

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    std::cout << "Array elements: ";
    printArrayWithPointer(numbers, size);
    std::cout << std::endl;
    
    return 0;
}

Cách 2: Dùng pointer increment

cpp
void printArrayWithPointer(int* arr, int size) {
    int* end = arr + size;  // Pointer đến "past-the-end"
    
    for (int* ptr = arr; ptr != end; ++ptr) {
        std::cout << *ptr << " ";
    }
}

Output:

Array elements: 10 20 30 40 50

🏆 Challenge 3: Memory Inspector

Yêu cầu

Viết chương trình tạo các biến thuộc các vùng nhớ khác nhau (Stack, Heap, Global) và in ra địa chỉ của chúng. Quan sát pattern địa chỉ.

cpp
#include <iostream>

// TODO: Khai báo biến global

int main() {
    // TODO: Khai báo biến local (stack)
    // TODO: Cấp phát biến trên heap
    
    std::cout << "=== Memory Inspector ===" << std::endl;
    
    // TODO: In địa chỉ của từng biến
    // Format: "Variable name (segment): address"
    
    // TODO: Giải phóng memory
    
    return 0;
}

Expected Output Pattern:

=== Memory Inspector ===
globalVar (DATA/BSS):  0x404xxx  (low address)
heapVar (HEAP):        0x55xxxx  (medium address)
localVar (STACK):      0x7fffxx  (high address)
💡 Gợi ý
  • Global variables: khai báo ngoài main()
  • Stack: biến local trong main()
  • Heap: dùng new
  • Dùng &variable để lấy địa chỉ
Lời giải
cpp
#include <iostream>
#include <iomanip>

// Global variable — .DATA segment (initialized)
int globalInit = 100;

// Global variable — .BSS segment (uninitialized → auto 0)
int globalUnInit;

int main() {
    // Stack variable
    int localVar = 42;
    
    // Heap variable
    int* heapVar = new int(200);
    
    std::cout << "=== Memory Inspector ===" << std::endl;
    std::cout << std::left;
    
    std::cout << std::setw(25) << "globalInit (DATA):" 
              << &globalInit << std::endl;
    
    std::cout << std::setw(25) << "globalUnInit (BSS):" 
              << &globalUnInit << std::endl;
    
    std::cout << std::setw(25) << "heapVar content (HEAP):" 
              << heapVar << std::endl;
    
    std::cout << std::setw(25) << "localVar (STACK):" 
              << &localVar << std::endl;
    
    std::cout << std::setw(25) << "heapVar pointer (STACK):" 
              << &heapVar << std::endl;
    
    // Analysis
    std::cout << "\n=== Analysis ===" << std::endl;
    std::cout << "Observe: DATA/BSS addresses are LOWER than HEAP" << std::endl;
    std::cout << "         HEAP addresses are LOWER than STACK" << std::endl;
    std::cout << "Memory layout: [TEXT | DATA | BSS | HEAP ↑ ... ↓ STACK]" << std::endl;
    
    // Cleanup
    delete heapVar;
    heapVar = nullptr;
    
    return 0;
}

Sample Output (addresses vary):

=== Memory Inspector ===
globalInit (DATA):       0x404018
globalUnInit (BSS):      0x404020
heapVar content (HEAP):  0x556b8c4f0eb0
localVar (STACK):        0x7ffd1a3b3a44
heapVar pointer (STACK): 0x7ffd1a3b3a48

=== Analysis ===
Observe: DATA/BSS addresses are LOWER than HEAP
         HEAP addresses are LOWER than STACK
Memory layout: [TEXT | DATA | BSS | HEAP ↑ ... ↓ STACK]

🎯 Bonus Challenge: Dynamic Array Sum

Yêu cầu (Nâng cao)

Viết chương trình:

  1. Hỏi user số lượng phần tử
  2. Cấp phát mảng động trên heap
  3. Nhập từng phần tử
  4. Tính tổng bằng pointer arithmetic
  5. Giải phóng memory đúng cách
Lời giải
cpp
#include <iostream>

int main() {
    int size;
    
    std::cout << "Nhập số lượng phần tử: ";
    std::cin >> size;
    
    if (size <= 0) {
        std::cerr << "Size phải > 0!" << std::endl;
        return 1;
    }
    
    // Cấp phát heap
    int* arr = new int[size];
    
    // Nhập phần tử
    std::cout << "Nhập " << size << " số:\n";
    for (int i = 0; i < size; ++i) {
        std::cout << "arr[" << i << "] = ";
        std::cin >> *(arr + i);  // Pointer arithmetic
    }
    
    // Tính tổng bằng pointer
    int sum = 0;
    int* end = arr + size;
    for (int* ptr = arr; ptr != end; ++ptr) {
        sum += *ptr;
    }
    
    std::cout << "Tổng: " << sum << std::endl;
    
    // ⚠️ CRITICAL: Giải phóng memory
    delete[] arr;  // delete[] cho arrays!
    arr = nullptr;
    
    return 0;
}

Output:

Nhập số lượng phần tử: 4
Nhập 4 số:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
Tổng: 100

📚 Đánh giá kết quả

ExerciseConcepts Covered
Challenge 1Pointers, Dereference, Pass by Pointer
Challenge 2Pointer Arithmetic, Arrays
Challenge 3Memory Layout, Stack/Heap/Data
BonusDynamic Allocation, Memory Management

➡️ Tiếp theo

🎉 Chúc mừng! Bạn đã hoàn thành Part 1: C++ Basics.

Quay lại C++ Engineering để tiếp tục với các modules khác.