Laporan kehadiran 0 bait dan baris yang rosak
Program kehadiran membaca fail kehadiran.csv yang mengandungi 250 baris untuk tahun 2024, setiap baris berbentuk tarikh,nama,status. Semasa ujian, atur cara gagal pada 31 Ogos kerana fail itu tiada (cuti umum). Pada baris ke-87, medan status kosong. Pada baris ke-142, nama 'Ahmad, bin Ali' mengandungi koma, jadi baris itu terpecah kepada empat medan dan bukan tiga. Selepas program dihentikan, guru mendapati laporan.txt yang sepatutnya mengandungi 250 baris ialah 0 bait. Atur cara membuka fail output, menulis setiap baris, dan hanya memanggil close() selepas gelung; tiada blok try digunakan. Guru mahu laporan tetap dihasilkan untuk hari persekolahan walaupun satu baris rosak, tetapi dia tidak mahu data hilang secara senyap atau laporan lama dimusnahkan oleh kegagalan separuh jalan.
1. Terangkan mengapa `laporan.txt` kosong walaupun berpuluh baris telah ditulis sebelum program berhenti. Cadangkan pembetulan yang turut melindungi laporan lama.
Read the worked answer
write() menulis ke penimbal (buffer) dalam memori, bukan terus ke cakera. Data benar-benar sampai ke fail apabila penimbal dipenuhkan, flush() dipanggil, atau fail ditutup. Dalam atur cara ini, pengecualian pada 31 Ogos menghentikan gelung dan melompat keluar; baris close() selepas gelung tidak pernah dilaksanakan, jadi penimbal dibuang dan laporan.txt kekal 0 bait. Fail juga kekal terbuka (file handle leak).
Lebih teruk, mod 'w' memotong fail sedia ada sebaik sahaja ia dibuka - jadi laporan hari sebelumnya sudah dimusnahkan sebelum satu baris baharu ditulis.
Pembetulan:
try:
with open('laporan.tmp', 'w') as f:
for baris in data:
f.write(bentuk(baris))
rename('laporan.tmp', 'laporan.txt') # hanya ganti jika selesai sepenuhnya
except IOError as e:
log(e) # laporan lama kekal utuh
Blok with menutup fail walaupun berlaku pengecualian, dan penulisan ke fail sementara kemudian dinamakan semula memastikan laporan separuh jalan tidak pernah kelihatan sah kepada guru.
2. Cadangkan strategi pengendalian untuk tiga masalah data (fail tiada, medan kosong, koma dalam nama) dan nyatakan bila program patut berhenti.
Read the worked answer
Asas keputusan: bezakan keadaan yang dijangka daripada kerosakan struktur data.
- Fail tiada pada 31 Ogos: cuti umum sudah diketahui, jadi ini keadaan dijangka. Rekodkan 'tiada sesi', jangan tulis 0% kepada mana-mana pelajar, dan catat dalam ringkasan. Tetapi jika fail tiada pada hari persekolahan, itu kegagalan sebenar - tandakan sebagai ralat dan jangan hasilkan laporan seolah-olah tiada kehadiran.
- Medan status kosong: baris tidak boleh ditafsirkan. Langkau baris itu, tetapi log nombor baris dan nama, dan kira dalam ringkasan 'ditolak'. Jangan anggap kosong sebagai 'tidak hadir'.
- Koma dalam nama: ini masalah format, bukan data. Penyelesaian betul ialah CSV dengan medan berpetik (
'Ahmad, bin Ali') atau penghurai CSV sebenar. Membahagi dengansplit(',')akan sentiasa rapuh; jika format tidak boleh diubah, bahagi maksimum dua kali dan ambil medan pertama serta terakhir.
Bila berhenti: berhenti apabila kerosakan struktur (bilangan medan salah pada kebanyakan baris, fail output tidak boleh ditulis) atau apabila kadar baris ditolak melebihi ambang yang ditetapkan, contohnya 5% daripada 250 baris. Hentikan juga jika fail input tiada pada hari persekolahan, kerana meneruskan akan menghasilkan laporan yang salah tetapi kelihatan lengkap.
3. Guru mencadangkan supaya setiap baris yang gagal dibaca hanya dilangkau. Bincangkan risiko cadangan ini untuk laporan kehadiran dan cara mengurangkan risiko tersebut.
Read the worked answer
Melangkau baris yang rosak kelihatan selamat, tetapi ia mengubah penyebut pengiraan. Jika 3 daripada 250 hari dilangkau, peratus kehadiran setiap pelajar dikira daripada 247 hari, bukan 250; pelajar yang hadir pada hari yang dilangkau tidak mendapat kredit, dan pelajar yang tidak hadir kelihatan lebih baik. Masalah ini senyap kerana laporan tetap kelihatan lengkap dan tiada siapa menyemak bilangan baris.
Cara mengurangkan risiko:
- Tetapkan bilangan hari persekolahan secara berasingan daripada fail (kalendar sekolah) dan gunakan nombor itu sebagai penyebut.
- Tandakan hari yang gagal dibaca sebagai 'tidak diketahui', bukan 'tidak hadir', supaya keputusan disiplin tidak dibuat atas data yang hilang.
- Cetak ringkasan liputan pada setiap laporan:
247/250 hari diproses, 3 ditolak (baris 87 dan 142, 31 Ogos). - Simpan baris yang ditolak ke fail
ralat.csvuntuk semakan manual, dan gagalkan proses jika kadar penolakan melebihi ambang yang dipersetujui.
Prinsipnya: melangkau satu rekod boleh diterima jika ia kelihatan dan boleh diaudit; melangkau secara senyap tidak boleh diterima dalam rekod kehadiran.