TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN TOÁN ỨNG DỤNG VÀ TIN HỌC ------ BÀI TẬP LỚN CUỐI KÌ Đề tài 1: Quản lý sinh viên, học phần, điểm thi Giáo viên hướng dẫn : TS Nguyễn Thị Thanh Huyền Sinh viên thực hiện : Vũ Văn Thành 20216885 Bộ môn : Kỹ thuật lập trình Mã lớp : 142298 Kỳ 20222 Vũ Văn Thành 20216885 Kỹ thuật lập trình Mục lục I. BÀI TOÁN THỰC TẾ. QUÁ TRÌNH THIẾT KẾ CHƯƠNG TRÌNH THEO PHƯƠNG PHÁP TINH CHỈNH TỪNG BƯỚC.Giới thiệu các cấu trúc dữ liệu tự tạo ra.Sinh viên và danh sách sinh viên.Học phần và danh sách học phần.Điểm thi và danh sách điểm thi.Quá trình thiết kế theo phương pháp tinh chỉnh từng bước.37 IV Hình ảnh thực hiện các chức năng của chương trình.Chức năng hiển thị thông tin sinh viên :.Chức năng thêm thông tin.Chức năng sửa thông tin.Chức năng xóa thông tin.Chức năng tìm kiếm thông tin.Chức năng tính GPA của toàn bộ sinh viên.Chức năng tìm điểm 1 học phần của toàn bộ sinh viên.Chức năng tìm kiếm sinh viên không đạt 1 học phần.Danh sách học phần mà 1 sinh viên chưa đạt.Điểm trung bình tích lũy của sinh viên.Chức năng sao lưu.File text ghi kết quả ra và quá trình thực thi chương trình.Đánh giá chung.Những điều đã làm được.Nhược điểm.ĐÁNH GIÁ CHI TIẾT.75 2 Vũ Văn Thành 20216885 Kỹ thuật lập trình I. BÀI TOÁN THỰC TẾ Mô tả bài toán: - Hệ thống quản lý sinh viên và điểm học phần là một chương trình dùng để quản lý thông tin về sinh viên, học phần và điểm số của sinh viên trong một trường đại học.
Hệ thống cho phép thêm, sửa, xóa thông tin sinh viên và học phần, cũng như nhập và hiển thị điểm số của sinh viên trong các học phần. Chức năng của hệ thống: - Nhập dữ liệu sinh viên và học phần: Người dùng có thể nhập thông tin của sinh viên, bao gồm mã số sinh viên, họ và tên, giới tính, ngày sinh. Cũng như thông tin về học phần, bao gồm mã học phần, tên môn học và số tín chỉ. - Nhập điểm học phần: Người dùng có thể nhập điểm học phần của sinh viên trong từng học phần cụ thể.
- Hiển thị danh sách sinh viên: Chương trình cho phép hiển thị danh sách toàn bộ sinh viên trong hệ thống, bao gồm mã số sinh viên, họ tên, giới tính, ngày sinh. - Bổ sung, xóa, sửa thông tin sinh viên và học phần: Người dùng có thể bổ sung thông tin mới, xóa thông tin sinh viên và học phần không cần thiết và sửa thông tin của sinh viên và học phần đã có. - Tính điểm trung bình chung tích lũy (GPA) của sinh viên: Hệ thống tính toán điểm trung bình chung tích lũy (GPA) của từng sinh viên dựa trên điểm số học phần đã nhập và hiển thị kết quả. - Hiển thị danh sách sinh viên không đạt học phần: Chương trình cho phép hiển thị danh sách sinh viên không đạt điểm học phần nào (điểm < 4) trong các học phần đã nhập.
- Hiển thị danh sách học phần chưa đạt: Chương trình cho phép hiển thị danh sách các học phần mà sinh viên chưa đạt (điểm < 4) trong các học phần đã nhập. - Hiển thị điểm học phần của sinh viên: Người dùng có thể nhập mã số sinh viên và học phần cụ thể và chương trình sẽ hiển thị điểm số của sinh viên trong học phần đó. Quy trình hoạt động của chương trình: - Người dùng nhập thông tin sinh viên và học phần. - Người dùng nhập điểm học phần cho sinh viên cụ thể.
- Người dùng có thể thực hiện các thao tác bổ sung, xóa và sửa thông tin sinh viên và học phần. - Hệ thống tính điểm trung bình chung tích lũy (GPA) cho từng sinh viên dựa trên điểm học phần đã nhập. 3 Vũ Văn Thành 20216885 Kỹ thuật lập trình - Người dùng có thể hiển thị danh sách toàn bộ sinh viên, danh sách sinh viên không đạt học phần, danh sách học phần chưa đạt, và điểm học phần của sinh viên theo yêu cầu. QUÁ TRÌNH THIẾT KẾ CHƯƠNG TRÌNH THEO PHƯƠNG PHÁP TINH CHỈNH TỪNG BƯỚC A.Gi ớ i thi ệ u các cấấu trúcữd ệli uự t ạ t o ra 1.Sinh viên và danh sách sinh viên a.Sinh viên : gồm các trường mã số sinh viên (int MSSV) , Họ đệm (string Ho_dem), Tên sinh viên (string Ten_sv), Giới tính (string Gioi_tinh), Ngày sinh (Ngay_Sinh *Ngay_sinh) Source code : struct Sinh_Vien { int j = 0; int MSSV; do string Ho_dem; { string Ten_sv; pos_of_delimiter_date = line.find(delimiter_date); string Gioi_tinh; string info_date = line.substr(0, pos_of_delimiter_date); Ngay_Sinh *Ngay_sinh; switch (j) { void load_sv(string line) case 0:ngay_sinh->day = stoi(info_date); break; { case 1:ngay_sinh->month = stoi(info_date); break; ngay_sinh = new Ngay_Sinh; case 2:ngay_sinh->year = stoi(info_date); break; string delimiter = ";"; } int pos_of_delimiter = line.find(delimiter); j++; int i = 0; line = line.substr(pos_of_delimiter_date + 1, do line.length() - 1); { } while (pos_of_delimiter_date != string::npos); pos_of_delimiter = line.find(delimiter); break; string info = line.substr(0, pos_of_delimiter); } switch (i) } { case 0: MSSV = stoi(info); break; i++; case 1: Ho_dem = info; break; line = line.substr(pos_of_delimiter + 1, line.length() - 1); case 2: ten_sv = info; break; } while (pos_of_delimiter != string::npos); case 3: gioi_tinh = info; break; case 4: } { string delimiter_date = "/"; void print() int pos_of_delimiter_date = line.find(delimiter_date); { cout << left; cout << "\t| " << setw(15) << MSSV << "|" << setw(25) << Ho_dem + " " + ten_sv << "|" << setw(13) << gioi_tinh << "|" << setw(17) << ngay_sinh->ngay_sinh() << "|\n"; } }; - Trong struct trên ta có viết sẵn 2 hàm dùng để thêm dữ liệu cho 1 biến sinh viên từ 1 chuỗi kí tự lấy ra trong file là load_sv() và 1 hàm dùng để in thông tin sinh viên là print() : + Hàm load_sv() sẽ lấy dữ liệu của 1 bản ghi có dạng như sau trong file : “MSSV;Họ đệm;Tên sinh viên;Giới tính;Ngày sinh\n” 4 Vũ Văn Thành 20216885 Kỹ thuật lập trình Ta sẽ đặt một kí tự tìm kiếm (delimiter) là kí tự chấm phẩy như trên : mỗi lần lấy ra một trường thông tin nào đó, ta sẽ lấy từ đầu chuỗi đến vị trí có dấu chấm phẩy (pos_of_delimiter), Sau khi lấy xong một trường thông tin thì cắt chuỗi từ vị trí đầu đến vị trí kí tự tìm kiếm trên : Mô tả quá trình hoạt động thuật toán như sau : “MSSV;Họ đệm;Tên sinh viên;Giới tính;Ngày sinh\n” cắt ra thông tin MSSV rồi gán vào con trỏ có kiểu Sinh_Vien Cập nhật lại chuỗi : “Họ đệm;Tên sinh viên;Giới tính;Ngày sinh\n” Tiếp tục với quy trình như vậy, riêng với ngày sinh thì có định dạng khác là day/month/year nên trong trường hợp còn chuỗi này ta phải đặt delimiter_date = “/”, rồi làm đệ quy như thuật toán bên trên.
+ Hàm print() in ra các trường thông tin của sinh viên theo thứ tự lần lượt như trên : nhưng có thêm các dấu “|” để kẻ sẵn 1 hàng trong khi in danh sách sinh viên, hàm còn sử dụng đến std::setw() và std::left của thư viện iomanip.h để căn chỉnh lại Terminal sao cho in ra cho đẹp.Nút sinh viên : gồm 1 con trỏ để ghi dữ liệu sinh viên và 1 con trỏ để chỉ đến nút tiếp theo. Source code : struct sv_node { Sinh_Vien* sinh_vien; sv_node* next; }; c.Danh sách sinh viên : gồm 1 con trỏ head chỉ vào đầu danh sách được cấp phát động bằng toán tử new, 1 hàm constructor để khởi tạo cho các con trỏ trong nút đầu được cấp phát động. Source code : struct SV_List head = temp_node; { temp_node->next = NULL; sv_node* head = new sv_node; } else { SV_List() // hàm khởi tạo (constructor) sv_node* p = head; { while (p->next != NULL) head->sinh_vien = new Sinh_Vien; { head->sinh_vien->Ngay_sinh = new Ngay_Sinh; p = p->next; head = NULL; } } p->next = temp_node; temp_node->next = NULL; } // hàm thêm thông tin từ 1 sinh viên có sẵn trong file void add_sv(Sinh_Vien* new_sv) } { // hàm kiểm tra xem 1 mã sinh viên có tồn tại trong danh sách // truyền dữ liệu cho con trỏ temp_node int check_sv(int ip_MSSV) sv_node* temp_node = new sv_node; { temp_node->sinh_vien = new Sinh_Vien; for (sv_node* p = head; p != NULL; p = p->next) temp_node->sinh_vien->Ngay_sinh = new Ngay_Sinh; { temp_node->sinh_vien->MSSV = new_sv->MSSV; if (ip_MSSV == p->sinh_vien->MSSV) temp_node->sinh_vien->Gioi_tinh = new_sv->Gioi_tinh; { chuan_hoa(new_sv->Ho_dem); return 1; temp_node->sinh_vien->Ho_dem = new_sv->Ho_dem; } chuan_hoa(new_sv->Ten_sv); 5 Vũ Văn Thành 20216885 Kỹ thuật lập trình temp_node->sinh_vien->Ten_sv = new_sv->Ten_sv; temp_node->sinh_vien->Ngay_sinh = new_sv->Ngay_sinh; } // thêm vào danh sách liên kết return 0; if (head == NULL) { } }; - Ở đây còn có thêm 1 hàm ( add_sv() )dùng để thêm sinh viên vào từ 1 con trỏ kiểu sinh viên có sẵn bằng cách khởi tạo 1 nút sinh viên temp_node rồi gán dữ liệu của con trỏ new_sv cho con trỏ sinh_vien của temp_node - Thuật toán để thêm 1 nút trong danh sách là o Nếu ban đầu danh sách rỗng, tức head = NULL thì head = temp_node và temp_node->next = NULL. o Nếu ban đầu danh sách không rỗng, tức head != NULL , thì tìm đến nút cuối(tức là nút có next = NULL) , ta gọi nút đó là p.
Khi đã tìm được rồi thì gán p->next = temp_node, temp->node = NULL. - Còn có thêm 1 hàm ( check_sv() ) dùng để kiểm tra xem 1 sinh viên có thuộc danh sách không bằng cách truyền vào mã số sinh viên và duyệt toàn bộ danh sách.H ọ c phấần và danh sách h ọc phấần a.Học phần : gồm trường mã học phần ( string Ma_hp), tên học phần (string Ten_hp), số tín chỉ (int So_tc) Source code : struct Hoc_Phan case 1: Ten_hp = info; break ; { case 2: So_tc = stoi(info); break; string Ma_hp; string Ten_hp; } int So_tc; i++; void load_hp(string line) line = line.substr(pos_of_delimiter + 1, line.length() - 1); { } while (pos_of_delimiter != string::npos); string delimiter = ";"; } int pos_of_delimiter = line.find(delimiter); int i = 0; void print() do { { cout << left; pos_of_delimiter = line.find(delimiter); cout << "\t| " << setw(15) << Ma_hp << "|" << setw(45) string info = line.