Menu
CoddyTech

Bộ lặp

Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 72 trên 104.

Bộ lặp (iterator) là các đối tượng đóng vai trò cầu nối giữa vùng chứa (container) và thuật toán (algorithm). Chúng cung cấp một cách truy cập thống nhất vào các phần tử trong mọi vùng chứa, bất kể vùng chứa đó lưu trữ dữ liệu nội bộ như thế nào. Hãy xem bộ lặp như một con trỏ tổng quát biết cách di chuyển qua vùng chứa.

Mọi vùng chứa STL đều cung cấp các phương thức begin() và end(). Trình lặp begin() trỏ đến phần tử đầu tiên, còn end() trỏ đến vị trí ngay sau phần tử cuối cùng, một dấu mốc cho biết cần dừng ở đâu:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> nums = {10, 20, 30};
    
    for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
        std::cout << *it << " ";  // Giải tham chiếu để lấy giá trị
    }
    // Đầu ra: 10 20 30
}

Từ khóa auto giúp khai báo iterator đơn giản hơn đáng kể:

for (auto it = nums.begin(); it != nums.end(); ++it) {
    *it *= 2;  // Thay đổi các phần tử (element) qua bộ lặp (iterator)
}
// nums giờ là {20, 40, 60}

Bộ lặp có nhiều loại khác nhau tùy theo khả năng. Bộ lặp truy cập ngẫu nhiên (như bộ lặp từ vector) hỗ trợ các phép toán số học như it + 3 hoặc it1 - it2.

Bộ lặp hai chiều (từ list, map) có thể di chuyển tiến và lùi bằng ++ và --. Bộ lặp tiến chỉ có thể di chuyển theo một hướng.

Để duyệt ngược, hãy dùng rbegin() và rend():

for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
    std::cout << *rit << " ";  // In ra theo thứ tự ngược lại
}
challenge icon

Thử thách

Dễ

Hãy xây dựng hệ thống theo dõi hàng tồn kho dùng trình lặp để duyệt và thao tác với tập hợp các mặt hàng. Bạn sẽ luyện tập cách dùng các loại trình lặp khác nhau để duyệt dữ liệu theo nhiều cách.

Bạn sẽ sắp xếp code trong hai tệp:

  • Inventory.h: Định nghĩa lớp Inventory quản lý tập hợp số lượng mặt hàng được lưu trong std::vector<int>.

    Lớp của bạn cần có các phương thức sau:

    • addItem(int quantity): thêm số lượng một mặt hàng vào kho
    • printForward(): dùng trình lặp với begin() và end() để in tất cả số lượng, cách nhau bằng dấu cách và theo sau là ký tự xuống dòng
    • printReverse(): dùng trình lặp ngược với rbegin() và rend() để in tất cả số lượng theo thứ tự ngược, cách nhau bằng dấu cách và theo sau là ký tự xuống dòng
    • doubleAll(): dùng trình lặp để duyệt mảng và nhân đôi tại chỗ từng số lượng
    • getTotal(): dùng trình lặp để tính và trả về tổng tất cả số lượng

    Dùng từ khóa auto khi khai báo trình lặp để code gọn gàng hơn.

  • main.cpp: Đọc bốn đầu vào số nguyên, mỗi số trên một dòng riêng, biểu thị số lượng mặt hàng.

    Tạo một đối tượng Inventory và thêm cả bốn số lượng vào đó. Sau đó, minh họa cách dùng trình lặp bằng cách:

    1. In Forward:, sau đó gọi printForward()
    2. In Reverse:, sau đó gọi printReverse()
    3. In Total: <sum> bằng getTotal()
    4. Gọi doubleAll() để thay đổi các số lượng
    5. In After doubling:, sau đó gọi printForward()
    6. In New total: <sum> bằng getTotal()

Ví dụ, với đầu vào 10, 25, 15 và 30:

Forward: 10 25 15 30 
Reverse: 30 15 25 10 
Total: 80
After doubling: 20 50 30 60 
New total: 160

Thử thách này giúp bạn luyện tập cả việc đọc phần tử thông qua trình lặp (để in và tính tổng) lẫn thay đổi phần tử thông qua trình lặp (để nhân đôi). Bạn cũng sẽ thấy trình lặp ngược giúp việc duyệt theo chiều ngược lại trở nên đơn giản mà không cần thao tác với chỉ số.

Tự làm thử

#include <iostream>
#include "Inventory.h"

using namespace std;

int main() {
    // Đọc bốn số nguyên đầu vào
    int q1, q2, q3, q4;
    cin >> q1;
    cin >> q2;
    cin >> q3;
    cin >> q4;

    // TODO: Tạo một đối tượng Inventory

    // TODO: Thêm cả bốn số lượng vào kho

    // TODO: In ra "Forward: " rồi gọi printForward()

    // TODO: In ra "Reverse: " rồi gọi printReverse()

    // TODO: In ra "Total: " rồi in kết quả của getTotal()

    // TODO: Gọi doubleAll() để thay đổi các số lượng

    // TODO: In ra "After doubling: " rồi gọi printForward()

    // TODO: In ra "New total: " rồi in kết quả của getTotal()

    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C++ online