Ôn thi HSG Tin học THPT – Bài 3: Cấu trúc rẽ nhánh và lặp

1. Mục tiêu

  • Hiểu và vận dụng thành thạo các cấu trúc rẽ nhánh điều kiện: if, elif, else.
  • Nắm vững và sử dụng hiệu quả các cấu trúc lặp: vòng lặp for (kết hợp với hàm range), và vòng lặp while.
  • Sử dụng chính xác các lệnh điều khiển vòng lặp: break và continue để thay đổi luồng thực thi của chương trình.

2. Giới thiệu và phạm vi ứng dụng

Trong lập trình, các câu lệnh thường được thực thi một cách tuần tự từ trên xuống dưới. Tuy nhiên, để giải quyết các bài toán phức tạp, chương trình cần có khả năng đưa ra quyết định và lặp lại các hành động.

Cấu trúc rẽ nhánh cho phép chương trình thực thi những khối lệnh khác nhau dựa trên các điều kiện cụ thể, trong khi cấu trúc lặp cho phép thực thi một khối lệnh nhiều lần. Đây là những khái niệm nền tảng, xuất hiện trong hầu hết mọi ngôn ngữ lập trình và là công cụ không thể thiếu để xây dựng logic cho chương trình.


3. Cú pháp và các ví dụ minh họa

3.1. Cấu trúc rẽ nhánh: if, elif, else

Cấu trúc này cho phép chương trình kiểm tra một điều kiện và thực thi một đoạn mã nguồn tương ứng nếu điều kiện đó là đúng.

3.1.1. Cấu trúc cú pháp chuẩn

Dạng if đơn:

if dieu_kien:
  # Khối lệnh được thực thi nếu dieu_kien là True

Dạng if-else:

if dieu_kien:
  # Khối lệnh được thực thi nếu dieu_kien là True
else:
  # Khối lệnh được thực thi nếu dieu_kien là False

Dạng if-elif-else:

if dieu_kien_1:
    # Khối lệnh được thực thi nếu dieu_kien_1 là True
elif dieu_kien_2:
    # Khối lệnh được thực thi nếu dieu_kien_1 là False và dieu_kien_2 là True
else:
    # Khối lệnh được thực thi nếu tất cả các điều kiện trên đều là False

3.1.2. Ví dụ 1: Kiểm tra một số nguyên dương

Chương trình kiểm tra xem một số nguyên n có phải là số dương hay không.

n = int(input("Nhập vào một số nguyên: "))
if n > 0:
  print(f"Số {n} là một số nguyên dương.")

3.1.3. Ví dụ 2: Kiểm tra tính chẵn lẻ

Chương trình xác định một số nguyên là chẵn hay lẻ bằng cách sử dụng phép toán chia lấy dư (%).

n = int(input("Nhập vào một số nguyên: "))
if n % 2 == 0:
    # Nếu n chia hết cho 2
    print(f"Số {n} là số chẵn.")
else:
    # Nếu n không chia hết cho 2
    print(f"Số {n} là số lẻ.")

3.1.4. Ví dụ 3: Xếp loại học lực

Chương trình xếp loại học lực dựa trên điểm trung bình.

diem_tb = float(input("Nhập điểm trung bình: "))

if diem_tb >= 8.0:
    print("Xếp loại: Giỏi")
elif diem_tb >= 6.5:
    print("Xếp loại: Khá")
elif diem_tb >= 5.0:
    print("Xếp loại: Trung bình")
else:
    print("Xếp loại: Yếu")

3.2. Cấu trúc lặp

3.2.1. Vòng lặp for và hàm range()

Vòng lặp for được sử dụng để lặp qua các phần tử của một đối tượng có thể duyệt (iterable) như chuỗi, danh sách, hoặc một dãy số được tạo bởi hàm range().

Cấu trúc cú pháp chuẩn:

for bien_lap in doi_tuong_duyet:
    # Khối lệnh lặp
Ví dụ 1: Vòng lặp cơ bản với range()

Hàm range(n) tạo ra một dãy số từ 0 đến n-1.

# In ra các số từ 0 đến 4
for i in range(5):
    print(i)
Ví dụ 2: Các biến thể của range()

Hàm range() có thể nhận 2 hoặc 3 tham số: range(start, stop)range(start, stop, step).

# In ra các số từ 2 đến 6
print("Các số từ 2 đến 6:")
for i in range(2, 7):
    print(i, end=' ') # end=' ' để in trên cùng một dòng
print() # In ký tự xuống dòng

# In ra các số chẵn từ 2 đến 10
print("Các số chẵn từ 2 đến 10:")
for i in range(2, 11, 2):
    print(i, end=' ')
print()

3.2.2. Vòng lặp while

Vòng lặp while thực thi một khối lệnh lặp đi lặp lại miễn là một điều kiện cho trước còn đúng.

Cấu trúc cú pháp chuẩn:

while dieu_kien:
    # Khối lệnh lặp

    # Cần có câu lệnh cập nhật để điều kiện có thể trở thành False
 Ví dụ 3: Đếm ngược từ 5
i = 5
while i > 0:
    print(i)
    i = i - 1 # Cập nhật biến điều kiện

print("Kết thúc!")

3.3. Các lệnh điều khiển vòng lặp: breakcontinue

3.3.1. Lệnh break

Lệnh break được sử dụng để chấm dứt ngay lập tức vòng lặp gần nhất chứa nó.

Ví dụ 4: Tìm số đầu tiên lớn hơn 20 và chia hết cho 7
for i in range(21, 101):
    if i % 7 == 0:
        print(f"Số đầu tiên tìm thấy là: {i}")
        break # Thoát khỏi vòng lặp ngay khi tìm thấy

3.3.2. Lệnh continue

Lệnh continue bỏ qua phần còn lại của khối lệnh trong lần lặp hiện tại và chuyển sang lần lặp tiếp theo.

Ví dụ 5: In ra các số từ 1 đến 10, bỏ qua số 5
for i in range(1, 11):
    if i == 5:
        continue # Bỏ qua lần lặp này và đi đến i = 6
    print(i, end=' ')

4. Trực quan hóa và gỡ lỗi với Thonny

Môi trường phát triển Thonny cung cấp một công cụ gỡ lỗi (debugger) mạnh mẽ, cho phép theo dõi từng bước thực thi của chương trình. Đây là một phương pháp hiệu quả để hiểu rõ cách các cấu trúc rẽ nhánh và lặp hoạt động.

Để sử dụng, hãy chép một trong các ví dụ trên vào Thonny và nhấn phím F7 (Step into) để thực thi từng dòng lệnh. Quan sát cách con trỏ thực thi (thường được tô màu vàng) di chuyển.

  • Với câu lệnh if, con trỏ sẽ nhảy vào khối lệnh tương ứng với điều kiện đúng và bỏ qua các khối lệnh còn lại.
  • Với vòng lặp for hoặc while, con trỏ sẽ lặp lại trên khối lệnh của vòng lặp và giá trị của biến lặp sẽ được cập nhật trong cửa sổ “Variables”.
  • Khi gặp lệnh break, con trỏ sẽ nhảy ra khỏi vòng lặp. Khi gặp continue, con trỏ sẽ ngay lập tức quay trở lại đầu vòng lặp cho lần lặp kế tiếp.

5. Bài tập vận dụng

5.1. Bài tập 1

5.1.1. Đề bài

Viết chương trình nhập vào một số nguyên dương n (n > 1) và kiểm tra xem n có phải là số nguyên tố hay không. Một số nguyên tố là số tự nhiên lớn hơn 1 và chỉ có hai ước là 1 và chính nó.

5.1.2. Lời giải và phân tích

  • Phân tích thuật toán:
    1. Nhập số nguyên n.
    2. Mặc định giả sử n là số nguyên tố. Ta có thể dùng một biến cờ (flag), ví dụ is_prime = True.
    3. Ta chỉ cần kiểm tra xem n có chia hết cho số nào trong khoảng từ 2 đến sqrt(n) hay không. Nếu n có một ước d > sqrt(n), thì nó phải có một ước k = n/d < sqrt(n).
      Do đó, nếu không tìm thấy ước nào trong khoảng [2, sqrt(n)], ta có thể kết luận n là số nguyên tố.
    4. Sử dụng vòng lặp for để duyệt qua các số i từ 2 đến phần nguyên của sqrt(n).
    5. Bên trong vòng lặp, nếu n chia hết cho i (n % i == 0), ta kết luận n không phải là số nguyên tố, đặt is_prime = False và thoát khỏi vòng lặp ngay lập tức bằng lệnh break.
    6. Sau khi vòng lặp kết thúc, kiểm tra giá trị của biến cờ is_prime để đưa ra kết luận cuối cùng.

Cài đặt:

import math # Thư viện toán học để sử dụng hàm căn bậc hai

n = int(input("Nhập vào một số nguyên dương n > 1: "))

# Mặc định is_prime là True
is_prime = True

if n <= 1:
    is_prime = False
else:
    # Lặp từ 2 đến căn bậc hai của n
    # int(math.sqrt(n)) + 1 để bao gồm cả giá trị căn bậc hai
    for i in range(2, int(math.sqrt(n)) + 1):
        # Nếu n chia hết cho i, n không phải số nguyên tố
        if n % i == 0:
            is_prime = False
            break # Thoát vòng lặp vì đã tìm thấy ước
if is_prime:
    print(f"{n} là số nguyên tố.")
else:
    print(f"{n} không phải là số nguyên tố.")

5.2. Bài tập 2

5.2.1. Đề bài

Viết chương trình nhập vào một số nguyên dương n và tính tổng các chữ số của nó. Ví dụ: Nếu n = 123, tổng là 1 + 2 + 3 = 6.

5.2.2. Lời giải và phân tích

  • Phân tích thuật toán:
    1. Nhập số nguyên dương n.
    2. Khởi tạo một biến tong_chu_so với giá trị ban đầu là 0.
    3. Sử dụng vòng lặp while với điều kiện lặp là n > 0.
    4. Trong mỗi lần lặp:
      • Lấy chữ số cuối cùng của n bằng phép toán chia lấy dư n % 10.
      • Cộng chữ số này vào biến tong_chu_so.
      • Loại bỏ chữ số cuối cùng của n bằng phép toán chia lấy phần nguyên n // 10.
    5. Khi n bằng 0, vòng lặp kết thúc. In ra giá trị của tong_chu_so.

Cài đặt:

n = int(input("Nhập vào một số nguyên dương n: "))

n_goc = n # Lưu lại giá trị ban đầu để in ra
tong_chu_so = 0

# Lặp cho đến khi n bằng 0
while n > 0:
    # Lấy chữ số cuối cùng
    chu_so = n % 10

    # Cộng vào tổng
    tong_chu_so += chu_so

    # Loại bỏ chữ số cuối cùng
    n = n // 10

print(f"Tổng các chữ số của {n_goc} là: {tong_chu_so}")

6. Các lưu ý và lỗi thường gặp

  • Lỗi vòng lặp vô hạn: Trong vòng lặp while, nếu biến điều kiện không bao giờ được cập nhật để trở thành False, chương trình sẽ chạy không ngừng.
  • Nhầm lẫn giữa ===: Phép gán = được dùng để đặt giá trị cho biến. Phép so sánh == được dùng để kiểm tra sự bằng nhau trong các điều kiện if, elif, while. Sử dụng if n = 5: sẽ gây ra lỗi cú pháp.
  • Lỗi thụt lề (IndentationError): Python sử dụng thụt lề để xác định các khối lệnh. Mọi dòng lệnh bên trong một khối (ví dụ, bên trong if hoặc for) phải được thụt lề một cách nhất quán (thường là 4 dấu cách).
  • Phạm vi của breakcontinue: Các lệnh này chỉ ảnh hưởng đến vòng lặp trong cùng mà chúng được đặt. Chúng không thể dùng để thoát khỏi các vòng lặp lồng nhau từ bên trong.

7. Tổng kết

Bài học đã trình bày các cấu trúc điều khiển luồng cơ bản và thiết yếu trong Python. Cấu trúc rẽ nhánh if-elif-else là công cụ để chương trình đưa ra quyết định. Các vòng lặp for và while cho phép tự động hóa các tác vụ lặp lại. Cuối cùng, các lệnh break và continue cung cấp khả năng kiểm soát chi tiết hơn đối với hành vi của vòng lặp.

Việc nắm vững các cấu trúc này là bước đệm quan trọng để xây dựng các thuật toán và chương trình máy tính phức tạp.


Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *