Giải Tin Học 10 trang 148

Lời giải chi tiết SGK Lớp 10 · Môn Tin Học · Trang 148–149

Chào các em! Hai trang này thuộc chủ đề kiểm thử và sửa lỗi chương trình. Cô sẽ tóm tắt phần lý thuyết rồi giải chi tiết các bài tập trong mục Luyện tập và Vận dụng nhé.

Tóm tắt lý thuyết

Nội dung xoay quanh việc kiểm thử chương trình tính ƯCLN bằng thuật toán Euclid (trừ liên tiếp). Có hai cách kiểm soát lỗi:

  • Cách 1 – In ra các giá trị trung gian: thêm biến đếm k và các lệnh print() để quan sát sự thay đổi của các biến qua từng vòng lặp.
  • Cách 2 – Dùng điểm dừng (breakpoint): đặt điểm dừng tại dòng bắt đầu vòng lặp while, chạy từng bước và ghi lại giá trị các biến vào bảng theo dõi.

Bảng theo dõi giá trị với m = 20, n = 16:

Vòng lặpmnKết quả
12016
2416
3412
448
Kết thúc lặp444

Kết luận: cả hai cách (in giá trị trung gian và đặt điểm dừng) đều hiệu quả để phát hiện và sửa lỗi.


LUYỆN TẬP

Bài 1: Lỗi ZeroDivisionError

Đề: Chương trình của em khi chạy phát sinh lỗi ngoại lệ ZeroDivisionError. Đó là lỗi gì và em sẽ xử lí lỗi này như thế nào?

Lời giải:

  • ZeroDivisionError là lỗi xảy ra khi chương trình thực hiện phép chia (/), chia lấy phần nguyên (//) hoặc lấy phần dư (%) mà mẫu số (số chia) bằng 0. Trong toán học phép chia cho 0 không xác định, nên Python báo lỗi ngoại lệ này.
  • Cách xử lí: kiểm tra số chia trước khi thực hiện phép chia, hoặc dùng cấu trúc try ... except để bắt và xử lí ngoại lệ.

Ví dụ cách 1 – kiểm tra trước:

a = int(input("Nhập a: "))
b = int(input("Nhập b: "))
if b != 0:
    print("a / b =", a / b)
else:
    print("Lỗi: không thể chia cho 0!")

Ví dụ cách 2 – dùng try/except:

try:
    print("a / b =", a / b)
except ZeroDivisionError:
    print("Lỗi: không thể chia cho 0!")

Bài 2: Chương trình tính tổng hai số

Đề: Chương trình sau có lỗi không? Nếu có thì tìm và sửa lỗi.

m = input("Nhập số tự nhiên m: ")
n = input("Nhập số tự nhiên n: ")
print("Tổng hai số đã nhập là:", m+n)

Lời giải:

Chương trình CÓ lỗi về mặt logic (lỗi ngữ nghĩa).

  • Hàm input() luôn trả về kiểu xâu (string), không phải kiểu số.
  • Vì vậy phép m + n không phải là phép cộng số học mà là phép nối hai xâu.
  • Ví dụ nhập m = 20, n = 16 thì kết quả in ra là 2016 chứ không phải 36.

Cách sửa: chuyển đổi dữ liệu nhập về kiểu số nguyên bằng int().

m = int(input("Nhập số tự nhiên m: "))
n = int(input("Nhập số tự nhiên n: "))
print("Tổng hai số đã nhập là:", m + n)

Sau khi sửa, nhập m = 20, n = 16 sẽ cho kết quả đúng là 36.


VẬN DỤNG

Bài 1: Chương trình sắp xếp dãy số

Đề: Chương trình sau có chức năng sắp xếp một dãy số cho trước. Hãy kiểm tra xem chương trình có lỗi không? Nếu có thì tìm và sửa lỗi.

A = [10,1,5,2,8,0,4]
for i in range(len(A)-1):
    j = i
    while j > 1 and A[j] < A[j-1]:
        A[j],A[j-1] = A[j-1],A[j]
        j = j - 1
print(A)

Lời giải:

Đây là thuật toán sắp xếp chèn (insertion sort). Chương trình CÓ hai chỗ sai về logic:

Lỗi 1 – Vòng lặp for bắt đầu sai chỉ số.

Với sắp xếp chèn, ta cần xét từng phần tử từ vị trí 1 trở đi để chèn về đúng chỗ trong phần đã sắp. Câu lệnh for i in range(len(A)-1) cho i chạy từ 0, đồng thời thiếu phần tử cuối. Cần cho i chạy từ 1 đến hết: range(1, len(A)).

Lỗi 2 – Điều kiện while j > 1 sai.

Để chèn phần tử về đúng vị trí, j phải có thể lùi tới tận vị trí 0, nghĩa là điều kiện phải là j > 0. Nếu để j > 1 thì phần tử không bao giờ được so sánh và đổi chỗ với phần tử đầu tiên (chỉ số 0), dẫn đến sắp xếp sai.

Chương trình đúng sau khi sửa:

A = [10,1,5,2,8,0,4]
for i in range(1, len(A)):
    j = i
    while j > 0 and A[j] < A[j-1]:
        A[j],A[j-1] = A[j-1],A[j]
        j = j - 1
print(A)

Kết quả khi chạy: [0, 1, 2, 4, 5, 8, 10] (dãy đã được sắp xếp tăng dần).

Giải thích thuật toán: với mỗi phần tử A[i], ta liên tục so sánh nó với phần tử liền trước. Nếu nó nhỏ hơn thì đổi chỗ và lùi về trước, lặp cho đến khi gặp phần tử nhỏ hơn hoặc về đầu dãy. Nhờ vậy phần đầu dãy luôn được giữ ở trạng thái đã sắp xếp.


Bài 2: Kiểm thử bằng bộ dữ liệu test

Đề: Để kiểm thử một chương trình, nếu chỉ bằng việc kiểm tra thông qua các bộ dữ liệu test thì có bảo đảm tìm ra hết lỗi của chương trình hay không? Vì sao?

Lời giải:

KHÔNG. Việc kiểm thử bằng các bộ dữ liệu test không bảo đảm tìm ra hết tất cả lỗi của chương trình.

Lí do:

  • Mỗi bộ dữ liệu test chỉ kiểm tra được một số trường hợp cụ thể, trong khi số lượng tình huống đầu vào có thể là rất lớn hoặc vô hạn, không thể thử hết được.
  • Một chương trình có thể chạy đúng với mọi bộ test đã chuẩn bị nhưng vẫn sai với những trường hợp đặc biệt mà ta chưa nghĩ tới (ví dụ: dãy rỗng, số 0, số âm, dữ liệu rất lớn, dữ liệu sai kiểu...).
  • Như nhà khoa học máy tính Edsger Dijkstra từng nói: "Kiểm thử chương trình có thể chứng minh sự tồn tại của lỗi, nhưng không bao giờ chứng minh được sự vắng mặt của lỗi."

Vì vậy, ngoài kiểm thử bằng bộ test, ta nên kết hợp thêm các phương pháp khác như đọc lại mã, kiểm soát giá trị trung gian, đặt điểm dừng và lựa chọn các bộ test bao quát nhiều trường hợp tiêu biểu (kể cả trường hợp biên, trường hợp đặc biệt).


Chế độ đọc sách →