C10-07 · Tìm lỗi: bản đọc lệnh

Xem dạng PDF

Gửi bài giải

Điểm: 1,00
Giới hạn thời gian: 2.0s
Giới hạn bộ nhớ: 256M
Input: stdin
Output: stdout

Tác giả:
Nguồn bài:
Sách "Lập trình cơ sở với Python"
Dạng bài
Ngôn ngữ cho phép
Python

Đề

Bài tìm lỗi của Chương 10. Chương trình dưới đây định làm đúng việc của bản đọc lệnh ở mục 10.3.4: đọc danh sách ban đầu gồm n sinh viên theo khung XS-07 (dòng mã sai bị bỏ qua lặng lẽ), rồi thực hiện m lệnh bằng quan_ly.chay_lenh, in kết quả của từng lệnh. Nhưng với ví dụ của mục 10.3.4 (Ví dụ 1 bên dưới), nó in 23010001 KHONG TIM THAY ở lệnh cuối; còn với n = 0 (Ví dụ 2) thì bị Runtime Error.

import quan_ly

for _ in range(int(input())):
    ds_sv = []
    sv = quan_ly.tao_sinh_vien(input())
    if sv is not None:
        ds_sv.append(sv)
for _ in range(int(input())):
    lenh = input().split()
    print("\n".join(quan_ly.chay_lenh(ds_sv, lenh)))

Hãy chỉ ra dòng gây ra cả hai lỗi, giải thích vì sao, sửa rồi nộp. Bài nộp phải in đúng như chương trình đúng của mục 10.3.4 (dùng quan_ly.py không sửa) với mọi dữ liệu thỏa ràng buộc.

Các lệnh (bảng của mục 10.1, bản đọc lệnh):

Lệnh Kết quả in
XEM mỗi sinh viên một dòng ma Ho Ten diem_hp loai theo thứ tự trong danh sách; rỗng: RONG
THEM ma ho ten qt ck ma DA THEM; mã sai: ma MA SAI; thiếu điểm, điểm là chữ, tên có dấu phẩy: LENH SAI; mã đã có: ma TRUNG
TIM ma dòng của sinh viên đó, hoặc ma KHONG TIM THAY
SUA ma qt ck / XOA ma ma DA SUA / ma DA XOA, hoặc ma KHONG TIM THAY
THONGKE năm dòng A so, …, F so
lệnh lạ, thiếu tham số, dòng trống LENH SAI

Dữ liệu vào

  • Dòng đầu: số nguyên n; n dòng tiếp theo, mỗi dòng ma ho ten diem_qt diem_ck (như C10-01).
  • Dòng tiếp: số nguyên m; m dòng tiếp theo, mỗi dòng một lệnh.

Kết quả

Với mỗi lệnh, theo thứ tự, các dòng kết quả như bảng trên.

Ràng buộc

  • 0 ≤ n ≤ 1000; 0 ≤ m ≤ 1000.
  • Mã sinh viên trong danh sách: 1–12 ký tự, chỉ gồm chữ số và chữ cái Latin; hợp lệ khi gồm đúng 8 chữ số. Các mã hợp lệ của danh sách ban đầu không trùng nhau.
  • Họ tên trong danh sách: 1–10 từ, mỗi từ 1–20 chữ cái Latin không dấu, hoa thường tùy ý; giữa các phần có thể có nhiều dấu cách.
  • Mỗi điểm trong danh sách thuộc [0; 10], dạng số nguyên hoặc một chữ số thập phân, dấu chấm hoặc dấu phẩy.
  • Mỗi dòng lệnh có thể trống; nếu không, gồm tối đa 14 phần cách nhau bởi dấu cách, mỗi phần 1–20 ký tự là chữ cái Latin, chữ số, dấu chấm, dấu phẩy hoặc dấu trừ. Tên lệnh là một trong sáu lệnh trên hoặc một từ lạ (không có TOP, TEN của C10-06).
  • XEM, THONGKE không có tham số; TIM, XOA nhiều nhất 1 tham số; SUA nhiều nhất 3 tham số.
  • Ở vị trí điểm của THEM, SUA: phần có chữ số luôn là số trong [0; 10] có tối đa 1 chữ số thập phân (SUA chỉ dùng dấu chấm); phần không có chữ số chỉ gồm chữ cái (không có nan, inf). Vì vậy các "chỗ hở" mà mục 10.4 nêu (điểm 11, SUA … 4,5) không xuất hiện ở bài này.

Gợi ý

Thử tay với n = 2: sau lượt đầu ds_sv có mấy người, sau lượt hai còn mấy? Với n = 0, thân vòng lặp chạy mấy lần, và tên ds_sv đã được gán lần nào chưa khi vòng lệnh dùng tới nó? Nộp một tệp: chép các hàm của quan_ly.py (phụ lục) lên đầu, bỏ import quan_ly và tiền tố quan_ly.. Đừng sửa quan_ly.py: lỗi không nằm ở đó.

Ví dụ 1

Dữ liệu vào:

2
23010001 Nguyen Van An 7.5 8.0
2301002 Tran Thi Binh 6.5 7.0
3
THEM 23010003 le minh DUC 8,0 8.8
TIM 23010003
XOA 23010001

Kết quả:

23010003 DA THEM
23010003 Le Minh Duc 8.5 A
23010001 DA XOA

Ví dụ 2

Dữ liệu vào:

0
1
XEM

Kết quả:

RONG

Giải thích ví dụ

  • Ví dụ 1 (ví dụ của mục 10.3.4): An hợp lệ; dòng 2301002 … có mã 7 chữ số nên bị bỏ qua — danh sách ban đầu chỉ có An. THEM thêm Duc (họ tên chuẩn hóa, 0,4 × 8 + 0,6 × 8,8 = 8,48 → 8,5 A), TIM thấy Duc, XOA 23010001 xóa An: 23010001 DA XOA. Bản lỗi lại in 23010001 KHONG TIM THAY, nghĩa là tới lúc xóa, An đã không còn trong ds_sv — hãy lần xem An mất ở bước nào.
  • Ví dụ 2: danh sách ban đầu rỗng nên XEM in RONG. Bản lỗi dừng với Runtime Error; đọc kỹ tên lỗi và dòng mà Python chỉ ra (Phụ lục C của sách) để biết tên nào chưa từng được gán.
  • Hai lỗi có chung một nguyên nhân và sửa được bằng cách sửa đúng một chỗ.

Phụ lục: các hàm của quan_ly.py (mục 10.3)

Chép nguyên từ sách (bỏ ba hàm đọc/ghi tệp CSV tach_dong_csv, ghi_danh_sach, doc_danh_sach vì bài nộp không dùng tệp). Hệ thống chấm chỉ nhận một tệp: chép các hàm này lên đầu bài nộp, bỏ dòng import quan_ly và bỏ tiền tố quan_ly. trước tên hàm.

def tinh_diem_hp(diem_qt, diem_ck):
    return round(0.4 * diem_qt + 0.6 * diem_ck, 1)


def xep_loai(diem_hp):
    if diem_hp >= 8.5:
        return "A"
    if diem_hp >= 7.0:
        return "B"
    if diem_hp >= 5.5:
        return "C"
    if diem_hp >= 4.0:
        return "D"
    return "F"


def chuan_hoa_ho_ten(ho_ten):
    return " ".join(ho_ten.split()).title()


def ma_sv_hop_le(ma):
    return len(ma) == 8 and ma.isdigit()


def tach_dong(dong):
    ma, phan_sau = dong.split(maxsplit=1)
    if not ma_sv_hop_le(ma):
        return None
    ho_ten, diem_qt, diem_ck = phan_sau.rsplit(maxsplit=2)
    diem_qt = float(diem_qt.replace(",", "."))
    diem_ck = float(diem_ck.replace(",", "."))
    return (ma, chuan_hoa_ho_ten(ho_ten), diem_qt, diem_ck)


def tao_sinh_vien(dong):
    ban_ghi = tach_dong(dong)
    if ban_ghi is None:
        return None
    ma, ho_ten, diem_qt, diem_ck = ban_ghi
    return {"ma": ma, "ho_ten": ho_ten, "diem_qt": diem_qt, "diem_ck": diem_ck}


def tim_theo_ma(ds_sv, ma):
    for sv in ds_sv:
        if sv["ma"] == ma:
            return sv
    return None


def them_sv(ds_sv, dong):
    ma = dong.split()[0]
    sv = tao_sinh_vien(dong)
    if sv is None:
        return ma + " MA SAI"
    if "," in sv["ho_ten"]:
        return "LENH SAI"
    if tim_theo_ma(ds_sv, ma) is not None:
        return ma + " TRUNG"
    ds_sv.append(sv)
    return ma + " DA THEM"


def sua_diem(ds_sv, ma, diem_qt, diem_ck):
    sv = tim_theo_ma(ds_sv, ma)
    if sv is None:
        return ma + " KHONG TIM THAY"
    sv["diem_qt"], sv["diem_ck"] = diem_qt, diem_ck
    return ma + " DA SUA"


def xoa_sv(ds_sv, ma):
    sv = tim_theo_ma(ds_sv, ma)
    if sv is None:
        return ma + " KHONG TIM THAY"
    ds_sv.remove(sv)
    return ma + " DA XOA"


def dong_bang_diem(sv):
    diem_hp = tinh_diem_hp(sv["diem_qt"], sv["diem_ck"])
    return " ".join([sv["ma"], sv["ho_ten"],
                     f"{diem_hp:.1f}", xep_loai(diem_hp)])


def bang_diem(ds_sv):
    if len(ds_sv) == 0:
        return ["RONG"]
    return [dong_bang_diem(sv) for sv in ds_sv]


def dem_theo_loai(ds_sv):
    dem = {}
    for sv in ds_sv:
        diem_hp = tinh_diem_hp(sv["diem_qt"], sv["diem_ck"])
        loai = xep_loai(diem_hp)
        dem[loai] = dem.get(loai, 0) + 1
    return dem


def thong_ke(ds_sv):
    dem = dem_theo_loai(ds_sv)
    return [loai + " " + str(dem.get(loai, 0))
            for loai in "ABCDF"]


def thuc_hien(ds_sv, lenh):
    if lenh[0] == "XEM":
        return bang_diem(ds_sv)
    if lenh[0] == "THONGKE":
        return thong_ke(ds_sv)
    if lenh[0] == "TIM":
        sv = tim_theo_ma(ds_sv, lenh[1])
        if sv is None:
            return [lenh[1] + " KHONG TIM THAY"]
        return [dong_bang_diem(sv)]
    if lenh[0] == "THEM":
        return [them_sv(ds_sv, " ".join(lenh[1:]))]
    if lenh[0] == "SUA":
        return [sua_diem(ds_sv, lenh[1],
                         float(lenh[2]), float(lenh[3]))]
    if lenh[0] == "XOA":
        return [xoa_sv(ds_sv, lenh[1])]
    return ["LENH SAI"]


def chay_lenh(ds_sv, lenh):
    try:
        return thuc_hien(ds_sv, lenh)
    except (ValueError, IndexError):
        return ["LENH SAI"]

Nguồn trong sách: Bài C10-07, mục 10.5, giáo trình Lập trình cơ sở với Python — TS. Nguyễn Quốc Long · Mức: (**)


Đang tải...