BÀI 4(JAVA): SỬ DỤNG CÁC CẤU TRÚC LẶP

4.1. Sử dụng vòng lặp while để lặp với điều kiện kiểm tra trước

4.1.1. Lý thuyết liên quan

  • Khái niệm: Vòng lặp while là cấu trúc lặp cơ bản nhất trong Java, liên tục thực thi khối lệnh bên trong thân khi biểu thức điều kiện trả về giá trị true. Biểu thức điều kiện được đánh giá ngay ở đầu vòng lặp; nếu điều kiện sai (false) ngay từ đầu thì thân vòng lặp sẽ không chạy lần nào.

  • Tác dụng: Để xử lý những bài toán lặp, mà số lần lặp chưa biết trước nhưng phụ thuộc vào sự biến đổi của trạng thái dữ liệu (như thuật toán tìm ước số chung, bài toán chia nguyên).

  • Ý nghĩa: Giúp kiểm soát điều kiện an toàn trước khi xử lý, tránh thực thi khối lệnh khi dữ liệu không thỏa mãn.

4.1.2. Trình tự thực hiện

B1: Khởi tạo biến điều khiển trước khi bước vào vòng lặp.

B2: Viết cấu trúc while (dieu_kien) kèm thân vòng lặp trong cặp ngoặc {}:

int n = 12345;
int tongChuSo = 0;
while (n > 0) {
    tongChuSo += (n % 10); // Lấy chữ số cuối cộng dồn
    n = n / 10;            // Bỏ chữ số cuối
}

B3: Luôn đảm bảo bên trong thân vòng lặp có câu lệnh làm thay đổi giá trị của biến điều khiển để hướng tới điều kiện dừng, tránh gây lặp vô hạn.

B4: Kiểm thử chương trình với các giá trị đầu vào đặc biệt (ví dụ: số 0 hoặc số âm).

Bài tập áp dụng

Bài tập 4.1.1: Đếm số chữ số của một số nguyên dương. Giải thích 

Yêu cầu: Khai báo một số nguyên dương long n = 9876543210L;. Dùng vòng lặp while liên tục chia nguyên cho 10 để đếm xem số n có bao nhiêu chữ số. In kết quả đếm ra màn hình.

Bài tập 4.1.2: Tìm ước số chung lớn nhất (USCLN) bằng giải thuật Euclid. Giải thích 

Yêu cầu: Cho hai số nguyên dương a = 48 và b = 18. Sử dụng vòng lặp while (b != 0) với thuật toán lấy dư r = a % b; a = b; b = r; để tìm và xuất ước chung lớn nhất của hai số ra màn hình.

4.2. Sử dụng vòng lặp do – while để kiểm tra điều kiện sau

4.2.1. Lý thuyết liên quan

  • Khái niệm: Vòng lặp do-while đánh giá biểu thức điều kiện ở cuối mỗi chu kỳ lặp. Do đó, thân vòng lặp luôn luôn được thực thi ít nhất một lần bất kể điều kiện ban đầu là đúng hay sai.

  • Tác dụng: Rất thích hợp để hiển thị bảng chọn (menu tương tác) hoặc ép buộc người dùng nhập dữ liệu đúng quy chuẩn từ bàn phím (nếu nhập sai thì bắt buộc nhập lại).

  • Ý nghĩa: Giảm thiểu mã nguồn trùng lặp khi cần xử lý hành động trước rồi mới kiểm tra kết quả. Cú pháp kết thúc bằng dấu chấm phẩy ; sau while(dieu_kien);.

4.2.2. Trình tự thực hiện:

  • B1: Mở khối lệnh bằng từ khóa do { ... }.

  • B2: Đặt các lệnh thực thi (nhập dữ liệu, hiển thị menu) vào bên trong thân vòng lặp.

  • B3: Viết điều kiện lặp lại sau từ khóa while kèm dấu chấm phẩy ; ở cuối:

    int tuoi;
    do {
        System.out.print("Nhập tuổi học sinh (từ 15 đến 30): ");
        tuoi = sc.nextInt();
    } while (tuoi < 15 || tuoi > 30); // Lặp lại nếu nhập sai
    
  • B4: Thực thi và thử nhập các giá trị sai để kiểm tra cơ chế lặp ép buộc.

Bài tập áp dụng

Bài tập 4.2.1: Nhập điểm số an toàn. Giải thích

Yêu cầu: Sử dụng Scanner và vòng lặp do-while để yêu cầu nhập điểm thực hành của học sinh. Điều kiện hợp lệ là điểm phải thuộc đoạn [0.0, 10.0]. Nếu nhập sai, xuất cảnh báo: “Điểm không hợp lệ, vui lòng nhập lại!” và tiếp tục lặp lại.

Bài tập 4.2.2: Menu xác nhận tiếp tục giao dịch. Giải thích

Yêu cầu: Viết chương trình mô phỏng một lần tính tiền. Sau khi tính xong, dùng do-while để hỏi: “Bạn có muốn tiếp tục giao dịch không? (Nhập 1 để tiếp tục, 0 để dừng): “. Vòng lặp sẽ tiếp tục chạy khi người dùng nhập 1 và chỉ dừng lại khi người dùng nhập 0.

4.3. Sử dụng vòng lặp for truyền thống và for-each nâng cao

4.3.1. Lý thuyết liên quan

  • Khái niệm:

    • Vòng lặp for gom cả 3 thành phần: khởi tạo biến đếm, kiểm tra điều kiện và cập nhật bước nhảy vào cùng một dòng lệnh. Biến điều khiển khai báo trong for chỉ tồn tại trong phạm vi của vòng lặp đó.

    • Vòng lặp for-each (Enhanced for loop) được dùng để duyệt tuần tự từng phần tử trong một mảng từ đầu đến cuối một cách tự động mà không cần dùng biến chỉ số i.

  • Tác dụng: for thích hợp với các bài toán đã biết trước số bước lặp hoặc cần chỉ số i; for-each giúp mã nguồn ngắn gọn, trực quan và ngăn ngừa hoàn toàn lỗi tràn chỉ số mảng.

  • Ý nghĩa: Tối ưu cấu trúc mã nguồn, dễ đọc, dễ kiểm tra và vận hành an toàn trên các tập dữ liệu.

4.3.2. Trình tự thực hiện

TH1: Sử dụng for cơ bản để xử lý dãy số:

for (int i = 1; i <= n; i++) {
    tong += i;
}

TH2: Sử dụng for-each để duyệt xuất các phần tử của một mảng:

double[] mangLuong = {7.5, 8.0, 9.2, 6.8};
for (double luong : mangLuong) {
    System.out.println("Mức lương: " + luong);
}

Ghi nhớ nguyên tắc: Biến lặp trong for-each mang tính chất chỉ đọc (read-only), không thể thay đổi giá trị phần tử mảng gốc thông qua biến này.

Bài tập áp dụng

Bài tập 4.3.1: In dãy số Fibonacci. Giải thích

Yêu cầu: Dùng vòng lặp for in ra N số đầu tiên của dãy Fibonacci (f0 = 0, f1 = 1, fn = fn-1 + fn-2) với N = 12. Các số in trên cùng một hàng ngang cách nhau dấu cách.

Bài tập 4.3.2: Tính tổng và đếm mảng bằng for-each. Giải thích

Yêu cầu: Khởi tạo mảng số nguyên int[] arr = {15, 24, 33, 40, 55, 60, 72};. Dùng vòng lặp for-each để duyệt mảng, tính tổng các phần tử chia hết cho 5 và in ra tổng cùng số lượng phần tử tìm thấy.

4.4. Sử dụng vòng lặp lồng nhau (Nested Loops) và điều khiển luồng với break, continue

4.4.1. Lý thuyết liên quan:

  • Khái niệm: Vòng lặp lồng nhau là việc đặt một cấu trúc lặp bên trong thân của một cấu trúc lặp khác. Với mỗi một lần lặp của vòng lặp ngoài, vòng lặp trong sẽ thực hiện toàn bộ chu trình lặp của nó.

  • Lệnh điều khiển:

    • break: Dừng và thoát ngay khỏi vòng lặp trong cùng chứa nó.

    • continue: Bỏ qua các câu lệnh còn lại trong thân vòng lặp hiện thời và nhảy sang lần lặp tiếp theo.

  • Tác dụng: Xử lý dữ liệu đa chiều (ma trận hàng/cột), vẽ các hình khối ký tự, giải thuật so sánh từng cặp phần tử (sắp xếp nổi bọt).

  • Ý nghĩa: Phát triển tư duy thuật toán bậc cao, rèn luyện kỹ năng kiểm soát độ phức tạp thời gian khi chạy lồng nhau.

4.4.2. Trình tự thực hiện:

  • B1: Thiết lập vòng lặp ngoài đại diện cho hàng (i) và vòng lặp trong đại diện cho cột (j).

  • B2: Đặt điều kiện can thiệp luồng bằng break hoặc continue:

    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= i; j++) {
            System.out.print("* ");
        }
        System.out.println(); // Xuống dòng khi xong một hàng
    }
    
  • B3: Kiểm tra số lần lặp thực tế để đảm bảo không bị quá tải bộ xử lý.

Bài tập 4.4.1: Vẽ hình tam giác vuông số. Giải thích và hướng dẫn

Yêu cầu: Sử dụng 2 vòng lặp for lồng nhau để in ra màn hình tam giác số có chiều cao h = 5 dòng:

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

Bài tập 4.2: In bảng cửu chương hoàn chỉnh từ 2 đến 9. Giải thích và hướng dẫn

Yêu cầu: Sử dụng 2 vòng lặp for lồng nhau: vòng lặp ngoài duyệt từ 2 đến 9, vòng lặp trong duyệt từ 1 đến 10 để xuất toàn bộ các phép nhân ra màn hình. Sử dụng \t để định dạng cột thẳng hàng đẹp mắt.