Giải Tin Học 10 trang 142
Lời giải chi tiết SGK Lớp 10 · Môn Tin Há»c · Trang 142–145
Bài 29: Nhận biết lỗi chương trình
⚠️ Phần văn bản gốc bị lỗi mã hóa khi quét, mình đã khôi phục lại nội dung chuẩn của bài học để giải. Nếu số liệu trong sách của em khác đôi chút thì cách làm vẫn giữ nguyên nhé.
🔍 Kiến thức cần nhớ
Trong Python, lỗi chương trình được chia thành 3 loại:
| Loại lỗi | Đặc điểm | Cách phát hiện |
|---|---|---|
| 1. Lỗi cú pháp (SyntaxError) | Viết sai cú pháp hoặc sai cấu trúc ngôn ngữ Python | Chương trình dừng ngay, chưa chạy đã báo lỗi |
| 2. Lỗi ngoại lệ (Exception) | Cú pháp đúng nhưng không thực hiện được một lệnh khi đang chạy (còn gọi là lỗi runtime) | Chương trình dừng giữa chừng, trả về một mã lỗi |
| 3. Lỗi logic (lỗi ngữ nghĩa) | Chương trình chạy hết, không báo lỗi nhưng kết quả sai | Không có mã lỗi, phải tự kiểm tra kết quả |
Một số mã lỗi ngoại lệ thường gặp:
| Mã lỗi | Mô tả |
|---|---|
| ZeroDivisionError | Thực hiện phép chia cho 0 |
| IndexError | Truy cập phần tử của danh sách nhưng chỉ số vượt quá giới hạn |
| NameError | Gọi một tên (biến/hàm) chưa được định nghĩa |
| TypeError | Lỗi kiểu dữ liệu (chỉ số không là số nguyên, toán hạng không phải số…) |
| ValueError | Giá trị của đối tượng không hợp lệ, ví dụ int("5.55") |
| IndentationError | Các dòng lệnh thụt vào không thẳng hàng / sai vị trí |
| SyntaxError | Lỗi cú pháp |
💡 Mẹo nhớ: Phân biệt nhanh 3 loại lỗi: - Chưa chạy đã báo lỗi → cú pháp - Đang chạy thì dừng + có mã lỗi → ngoại lệ - Chạy xong êm xuôi nhưng kết quả sai → logic
⚙️ Bài tập
Câu 1 (Hoạt động 1)
Đề bài: Khi gõ sai cú pháp một lệnh, chương trình sẽ dừng lại và báo lỗi, đó là lỗi loại gì?
Trả lời:
Đó là lỗi cú pháp (SyntaxError) – loại lỗi thứ nhất.
Đặc điểm của lỗi này là Python phát hiện được ngay khi chương trình chưa kịp chạy. Vì câu lệnh sai cấu trúc mà ngôn ngữ Python quy định nên trình thông dịch lập tức dừng lại và thông báo lỗi.
Ví dụ: while(a (thiếu dấu đóng ngoặc) sẽ báo SyntaxError.
Câu 2 (Hoạt động 1)
Đề bài: Bài toán yêu cầu sắp xếp dãy số ban đầu thành dãy tăng dần. Giả sử dãy ban đầu là [2, 4, 5, 1, 3], kết quả thu được là một dãy chưa được sắp xếp đúng (ví dụ [2, 4, 1, 3, 5]). Chương trình có lỗi không? Nếu có thì lỗi đó thuộc loại gì?
Trả lời:
Chương trình có lỗi.
Lập luận: chương trình vẫn chạy bình thường đến hết, không bị dừng, không có mã lỗi nào được trả về. Tuy nhiên kết quả không đúng yêu cầu (dãy chưa tăng dần). Đây chính là dấu hiệu của lỗi logic (lỗi ngữ nghĩa) bên trong chương trình – loại lỗi thứ ba.
⚠️ Lưu ý thi: Lỗi logic là loại nguy hiểm và khó tìm nhất vì máy không hề báo. Đề thi hay cho một đoạn chương trình "chạy được nhưng kết quả sai" rồi hỏi loại lỗi → đáp án là lỗi logic.
Câu 3 (Hoạt động 2)
Đề bài: Hãy nêu mã lỗi ngoại lệ của mỗi lệnh sau (nếu xảy ra lỗi):
a) a[1.5] (với a là một danh sách)
b) 1/0
c) 10 % "3.5"
d) 12 + (10)
Trả lời từng ý:
a) a[1.5] → TypeError
Chỉ số dùng để truy cập phần tử của danh sách bắt buộc phải là số nguyên. Ở đây 1.5 là số thực nên Python báo lỗi kiểu dữ liệu.
b) 1/0 → ZeroDivisionError
Phép chia có mẫu số bằng 0, không xác định được giá trị.
c) 10 % "3.5" → TypeError
Toán tử % (chia lấy dư) đòi hỏi cả hai toán hạng là số. Ở đây "3.5" là một xâu kí tự nên sai kiểu dữ liệu.
Nếu đề của em là 10 % 3.5 (hai số) thì không sinh lỗi, kết quả là 3.0.
d) 12 + (10) → Không sinh lỗi
Đây là phép cộng hai số nguyên hợp lệ, kết quả bằng 22.
💡 Mẹo nhớ: "Sai chỉ số / sai kiểu toán hạng" → TypeError; "vượt quá giới hạn danh sách" → IndexError. Đừng nhầm hai lỗi này.
Câu 4 (Thực hành – Nhiệm vụ 1)
Đề bài: Viết chương trình nhập hai số nguyên m, n từ bàn phím (cách nhau bởi dấu cách), đưa ra tổng, hiệu, thương của hai số. Phân tích các khả năng sinh lỗi.
Chương trình
a = input("Nhập hai số m, n (cách nhau dấu cách): ")
b = a.split() # tách xâu thành danh sách các xâu con
m, n = int(b[0]), int(b[1]) # chuyển thành hai số nguyên
print("Tổng:", m + n)
print("Hiệu:", m - n)
print("Thương:", m / n)
Các khả năng sinh lỗi
| Tình huống | Mã lỗi | Lí do |
|---|---|---|
| m hoặc n nhập vào không là số nguyên (vd nhập chữ) | ValueError | Hàm int() không chuyển được |
| Giữa hai số không có dấu cách | IndexError | b chỉ có 1 phần tử nên b[1] vượt giới hạn |
| Số n nhập vào là 0 | ZeroDivisionError | Phép tính m / n chia cho 0 |
Câu 5 (Thực hành – Nhiệm vụ 2)
Đề bài: Viết chương trình nhập số tự nhiên n, sau đó nhập lần lượt n số nguyên đưa vào danh sách A. Nhập xong, in danh sách A. Phân tích các khả năng sinh lỗi.
Chương trình
n = int(input("Nhập số tự nhiên n: "))
A = []
for i in range(n):
x = int(input("Nhập số hạng thứ " + str(i + 1) + ": "))
A.append(x)
print("Danh sách A:", A)
Các khả năng sinh lỗi
- Số n nhập vào không là số nguyên → ValueError (do
int()không chuyển được). - Mỗi số hạng của danh sách nhập vào không là số nguyên → ValueError.
Câu 6 (Luyện tập 1)
Đề bài: Các lệnh sau có sinh lỗi chương trình không? Nếu có thì mã lỗi là gì?
Đoạn 1:
>>> A = [1, 3, 5, 10, 0]
>>> for i in range(1, len(A) + 1):
print(A[i])
Đoạn 2:
>>> a, b = "101010", 1010101
>>> c = a + b
Trả lời:
Đoạn 1 → có lỗi: IndexError
Danh sách A có 5 phần tử, chỉ số hợp lệ là 0 → 4.
range(1, len(A) + 1) = range(1, 6) cho i nhận các giá trị 1, 2, 3, 4, 5.
Khi i = 5, lệnh A[5] truy cập phần tử thứ 6 không tồn tại → IndexError (chỉ số vượt quá giới hạn).
Đoạn 2 → có lỗi: TypeError
a là xâu kí tự "101010", b là số nguyên 1010101. Phép a + b cố cộng một xâu với một số → không cùng kiểu dữ liệu → TypeError.
⚠️ Lưu ý thi: Lỗi vòng lặp ở đoạn 1 cực kì hay gặp khi dùnglen(A) + 1. Để duyệt hết danh sách đúng cách hãy dùngrange(len(A))(chỉ số chạy từ 0 đến len(A)−1).
Câu 7 (Luyện tập 2)
Đề bài: Để tính giá trị trung bình của một danh sách số A, người lập trình dùng lệnh:
tb = sum(A) / len(A)
Lệnh này có thể sinh lỗi ngoại lệ không? Nếu có thì là những lỗi gì?
Trả lời:
Lệnh này có thể sinh lỗi ngoại lệ trong hai trường hợp:
- Danh sách A rỗng (
A = []): khi đólen(A) = 0, lệnh trở thành phép chia cho 0 → ZeroDivisionError.
- A chứa phần tử không phải là số (vd có một xâu kí tự): hàm
sum(A)không cộng được các phần tử khác kiểu → TypeError.
🧩 Vận dụng
Câu 1 (Vận dụng 1)
Đề bài: Viết chương trình nhập số tự nhiên n từ bàn phím, kết quả đưa ra là danh sách các ước số thực sự của n (tính cả 1 nhưng không tính n). Kiểm tra các khả năng sinh lỗi.
Chương trình
n = int(input("Nhập số tự nhiên n: "))
uoc = []
for i in range(1, n): # i chạy từ 1 đến n - 1 (không lấy n)
if n % i == 0:
uoc.append(i)
print("Các ước số thực sự của", n, "là:", uoc)
Giải thích: ước số thực sự của n là các số chia hết n nhưng nhỏ hơn n, vì vậy chỉ duyệt i trong range(1, n) và kiểm tra điều kiện n % i == 0.
Khả năng sinh lỗi
- n nhập vào không phải số nguyên → ValueError (hàm
int()báo lỗi).
💡 Có thể bổ sung kiểm tra n ≥ 1 để chương trình ý nghĩa hơn, nhưng đề chỉ yêu cầu xét lỗi sinh ra nên ValueError là lỗi chính.
Câu 2 (Vận dụng 2)
Đề bài: Viết một chương trình nhỏ để khi chạy sẽ sinh mã lỗi NameError.
Chương trình
print(x) # x chưa hề được khai báo/gán giá trị
Khi chạy, Python đi tìm tên x nhưng không thấy nên báo:
NameError: name 'x' is not defined
Cách khác cũng cho NameError là gọi một hàm chưa định nghĩa:
xinchao() # chưa định nghĩa hàm xinchao
💡 Mẹo nhớ: NameError = "gọi tên ma" – gọi biến hoặc hàm chưa tồn tại.
🎯 Ghi nhớ: Python có 3 loại lỗi – cú pháp (chưa chạy đã dừng), ngoại lệ (đang chạy thì dừng + có mã lỗi), logic (chạy xong nhưng kết quả sai, không báo lỗi). Khi gặp một câu lệnh, hãy tự hỏi: chia cho 0 chưa (ZeroDivisionError), chỉ số có vượt giới hạn không (IndexError), kiểu dữ liệu có khớp không (TypeError), giá trị chuyển đổi có hợp lệ không (ValueError), tên đã định nghĩa chưa (NameError). Nắm chắc 5 câu hỏi này là làm gọn mọi bài về lỗi ngoại lệ.
