



















Preview text:
  lOMoAR cPSD| 60729183
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ ĐÔNG Á 
KHOA CÔNG NGHỆ THÔNG TIN  
HỌC PHẦN: CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT     MÃ ĐỀ THI: 3  
TÊN ĐỀ TÀI: XÂY DỰNG BÀI TOÁN QUẢN LÍ  
SÁCH SỬ DỤNG DANH SÁCH LIÊN KẾT ĐƠN LỚP 
TÍN CHỈ: CSDL.03.K13.01.LH.C04      
Giảng viên hướng dẫn: ThS. Mai Văn Linh  
 Danh sách sinh viên thực hiện: Nhóm 6              Bắc Ninh – 2025       lOMoAR cPSD| 60729183      MỤC LỤC     
Lời nói đầu ............................................................................................... 4 
Chương 1. TỔNG QUAN VỀ ĐỀ TÀI .................................................. 4 
1.1. Giới thiệu đề tài....................................................................................................... 4 
CHƯƠNG 2: PHÂN TÍCH ĐỀ TÀI ...................................................... 5 
2.1. Dữ liệu lưu trữ ........................................................................................................ 5 
2.2. Cấu trúc dữ liệu ...................................................................................................... 5 
2.3. Các chức năng chính .............................................................................................. 5 
2.4. Thiết kế menu .......................................................................................................... 6 
2.4.1. Menu chính (Login Menu) .................................................................................. 6 
2.4.2. Menu quản trị viên (Admin Menu) .................................................................... 7 
2.4.3. Menu sinh viên (Student Menu) ......................................................................... 7 
2.4.4. Thiết kế giao diện hiển thị ................................................................................... 8 
CHƯƠNG 3: PHÂN TÍCH CHƯƠNG TRÌNH ................................... 8 
3.1. Khai báo thư viện .................................................................................................. 8 
3.2. Khởi tạo nút ............................................................................................................ 9 
3.3. Nhập dữ liệu .......................................................................................................... 10 
3.4. Hiển thị danh sách ................................................................................................ 11 
3.5. Thêm vào đầu danh sách ...................................................................................... 12 
3.6. Chèn vào cuối danh sách ...................................................................................... 13 
3.7. Xóa sách theo mã sách ......................................................................................... 14 
3.8. Tìm kiếm theo mã sách ........................................................................................ 14 
3.9. Thoát chương trình .............................................................................................. 14    lOMoAR cPSD| 60729183
CHƯƠNG 4: MÃ NGUỒN CHƯƠNG TRÌNH ................................. 15 
4.1. Mã nguồn ............................................................................................................... 15 
Kết luận .................................................................................................. 32 
Danh mục sách tham khảo ................................................................... 33      lOMoAR cPSD| 60729183      Lời nói đầu 
Trong bối cảnh công nghệ thông tin phát triển mạnh mẽ như hiện nay, việc ứng dụng các 
cấu trúc dữ liệu và giải thuật vào xây dựng các hệ thống quản lý đã trở thành nhu cầu thiết 
yếu. Bài báo cáo này trình bày chi tiết về việc thiết kế và triển khai " Bài toán quản lý sách 
sử dụng danh sách liên kết đơn " - một ứng dụng quan trọng trong công tác quản lý sách và 
giao dịch mượn-trả tại các thư viện. 
Danh sách liên kết đơn được lựa chọn làm nền tảng cho hệ thống nhờ những ưu điểm vượt 
trội trong việc quản lý dữ liệu động, dễ dàng mở rộng và hiệu quả trong các thao tác 
thêm/xóa dữ liệu. Đây cũng là cấu trúc dữ liệu cơ bản nhưng đầy sức mạnh, giúp sinh viên 
có thể hiểu rõ nguyên lý hoạt động của các cấu trúc dữ liệu phức tạp hơn. 
Bài báo cáo được chia thành các phần chính: phân tích yêu cầu hệ thống, thiết kế cấu trúc 
dữ liệu, triển khai các giải thuật cơ bản, cùng với đánh giá ưu nhược điểm của phương pháp 
tiếp cận. Đặc biệt, chúng tôi tập trung làm rõ cách thức vận hành của từng chức năng quan 
trọng như quản lý giao dịch mượn-trả sách, tìm kiếm thông tin, và các thao tác cơ bản trên  danh sách liên kết. 
Thông qua báo cáo này, em mong muốn cung cấp một tài liệu tham khảo hữu ích cho những 
ai quan tâm đến việc ứng dụng cấu trúc dữ liệu vào giải quyết các bài toán thực tế, đồng 
thời chia sẻ kinh nghiệm trong quá trình triển khai hệ thống quản lý bằng ngôn ngữ C. 
Mặc dù đã cố gắng hoàn thiện, song báo cáo không tránh khỏi những thiếu sót. Em rất 
mong nhận được những ý kiến đóng góp quý báu từ quý thầy cô và các bạn để hệ thống có 
thể phát triển hoàn thiện hơn trong tương lai.       
Chương 1. TỔNG QUAN VỀ ĐỀ TÀI 
1.1. Giới thiệu đề tài 
Đề tài "Xây dựng bài toán quản lý sách sử dụng danh sách liên kết đơn" là một ứng 
dụng thực tế trong lĩnh vực quản lý thư viện và khoa học máy tính. Hệ thống này tập trung 
vào việc quản lý các giao dịch mượn-trả sách trong thư viện bằng cách sử dụng cấu trúc dữ 
liệu danh sách liên kết đơn. 
Danh sách liên kết đơn (singly linked list) là cấu trúc dữ liệu động, mỗi phần tử (node) chứa 
dữ liệu và con trỏ trỏ tới phần tử tiếp theo. Trong hệ thống này, danh sách liên kết đơn được      lOMoAR cPSD| 60729183  
sử dụng để lưu trữ thông tin các giao dịch mượn sách, giúp quản lý hiệu quả với các ưu  điểm:  • 
Dễ dàng thêm/xóa phần tử  • 
Tiết kiệm bộ nhớ khi không cần cấp phát trước  • 
Linh hoạt trong quản lý dữ liệu động       
CHƯƠNG 2: PHÂN TÍCH ĐỀ TÀI 
2.1. Dữ liệu lưu trữ 
Hệ thống quản lý các thông tin sau về giao dịch mượn sách:  • 
Mã sách (bookId): kiểu int - định danh duy nhất cho mỗi cuốn sách  • 
Tên ngành (branchName): kiểu string[100] - chuyên ngành của sách  • 
Thời gian mượn (duration): kiểu int - số ngày mượn  • 
Số thẻ sinh viên (rollNumber): kiểu int - định danh người mượn  • 
Số điện thoại (mobileNumber): kiểu long long - liên hệ người mượn  • 
Ngày mượn: sử dụng macro DATE của C 
2.2. Cấu trúc dữ liệu  
struct details { char branchName[100]; // 
Tên ngành sách int bookId; // Mã  sách 
 int duration; // Thời gian mượn (ngày) 
int rollNumber; // Số thẻ sinh viên long 
long int mobileNumber; // Số điện thoại struct 
details *next; // Con trỏ tới node tiếp theo  }; 
2.3. Các chức năng chính  
1. Tạo bản ghi mượn sách (createRecord)      lOMoAR cPSD| 60729183  
• Thêm node mới vào cuối danh sách 
• Kiểm tra trùng mã sách 
• Tăng biến đếm tổng sách đã mượn (total) 
2. Xóa bản ghi trả sách (deleteRecord)  • Xóa node theo mã sách 
• Xử lý 3 trường hợp: xóa đầu danh sách, xóa cuối danh sách, xóa giữa  danh sách 
• Giảm biến đếm tổng sách đã mượn 
3. Hiển thị toàn bộ bản ghi (displayRecords) 
• Duyệt toàn bộ danh sách từ đầu đến cuối 
• Hiển thị thông tin định dạng bảng 
4. Tìm kiếm bản ghi theo số thẻ (findRecord) 
• Duyệt danh sách tìm node có rollNumber khớp 
• Hiển thị tất cả sách sinh viên đã mượn 
5. Thay đổi mật khẩu admin (changePassword) 
• Kiểm tra mật khẩu cũ 
• Cập nhật mật khẩu mới   
2.4. Thiết kế menu  
2.4.1. Menu chính (Login Menu)     Hình 1: Login Menu   Chức năng: 
• Là giao diện đầu tiên khi khởi động chương trình 
• Phân quyền truy cập cho 2 đối tượng: quản trị viên và sinh viên 
• Lựa chọn thoát chương trình      lOMoAR cPSD| 60729183       
2.4.2. Menu quản trị viên (Admin Menu)     Hình 2: Admin Menu  
Chức năng chi tiết: 
• Tạo bản ghi mượn sách: Thêm thông tin mượn sách mới vào hệ thống 
• Xóa bản ghi trả sách: Xóa bản ghi khi sinh viên trả sách 
• Hiển thị tất cả bản ghi: Xem toàn bộ giao dịch mượn sách đang có 
• Đổi mật khẩu: Thay đổi mật khẩu đăng nhập quản trị 
• Thoát: Quay lại menu chính         
2.4.3. Menu sinh viên (Student Menu)    Hình 3:Studen Menu       lOMoAR cPSD| 60729183  
Chức năng chi tiết: 
• Xem bản ghi mượn sách: Hiển thị danh sách sách sinh viên đang mượn (tìm  theo số thẻ) 
• Đăng xuất: Quay lại menu chính   
2.4.4. Thiết kế giao diện hiển thị 
1. Giao diện hiển thị tất cả bản ghi     
Hình 4: Giao diện hiển thị tất cả bản ghi  
2. Giao diện hiển thị bản ghi sinh viên     
Hình 5: Giao diện bản ghi sinh viên       
CHƯƠNG 3: PHÂN TÍCH CHƯƠNG TRÌNH   
3.1. Khai báo thư viện 
Chương trình sử dụng các thư viện C chuẩn sau: 
1. stdio.h - Thư viện nhập/xuất chuẩn: 
• Cung cấp các hàm cơ bản: printf(), scanf() 
• Hỗ trợ thao tác với file (mặc dù chưa sử dụng trong phiên bản hiện tại) 
• Macro __DATE__ để lấy ngày hiện tại 
2. string.h - Thư viện xử lý chuỗi:      lOMoAR cPSD| 60729183  
• Sử dụng hàm strcmp() để so sánh mật khẩu 
• Hàm strcpy() để sao chép mật khẩu 
• Các thao tác xử lý chuỗi khác 
3. malloc.h - Thư viện quản lý bộ nhớ động: 
• Cung cấp hàm malloc() để cấp phát bộ nhớ cho các node mới 
• Hàm free() để giải phóng bộ nhớ khi xóa node 
4. locale.h (được đề xuất thêm) - Thư viện hỗ trợ địa phương hóa: 
• Hàm setlocale() để thiết lập locale phù hợp hiển thị tiếng Việt 
• Giúp hiển thị đúng các ký tự có dấu 
5. stdlib.h (ngầm định) - Thư viện tiện ích chuẩn: 
• Hỗ trợ hàm system() để gọi lệnh hệ thống ("cls" để xóa màn hình) 
• Các hàm quản lý bộ nhớ khác Các thư viện này được chọn vì: 
• Đủ để triển khai các chức năng cơ bản của hệ thống 
• Nhẹ và hiệu quả cho bài toán quản lý thư viện 
• Tương thích tốt trên nhiều nền tảng 
• Hỗ trợ đầy đủ các thao tác với cấu trúc dữ liệu danh sách liên kết    3.2. Khởi tạo nút 
Trong chương trình, việc khởi tạo nút được thực hiện thông qua các bước sau: 
1. Cấu trúc dữ liệu nút:  struct details { 
 char branchName[100]; // Tên ngành sách int 
bookId; // Mã sách int duration; // 
Thời gian mượn (ngày) int rollNumber; // 
Số thẻ sinh viên long long int mobileNumber; 
// Số điện thoại struct details *next; // Con trỏ  tới node tiếp theo  };        lOMoAR cPSD| 60729183  
2. Khởi tạo nút mới: 
struct details *new_node = (struct details *)malloc(sizeof(struct details));   
3. Quy trình khởi tạo: 
• Cấp phát bộ nhớ động bằng hàm malloc() 
• Kiểm tra nếu cấp phát thành công (trong code chính đã bỏ qua bước kiểm tra  này) 
• Khởi tạo con trỏ next thành NULL khi thêm vào cuối danh sách         3.3. Nhập dữ liệu 
Quá trình nhập dữ liệu được thực hiện trong hàm createRecord():  1. Nhập mã sách:  printf("Nhap ma sach: ");  scanf("%d", &bId);   
// Kiểm tra trùng mã sách  searchResult = search(bId);  if (searchResult == bId) { 
 printf("Sach nay khong co san (da duoc muon)\n");  return start;  }   
2. Nhập thông tin chi tiết: printf("Nhap nganh: "); scanf("%s", &branch);   
printf("Nhap thoi gian muon (ngay): ");  scanf("%d", &dur);   
printf("Nhap so the day du: ");  scanf("%d", &rollNo);      lOMoAR cPSD| 60729183    
printf("Nhap so dien thoai: ");  scanf("%lld", &mobileNo);        
3. Gán dữ liệu vào nút: 
strcpy(new_node->branchName, branch); 
new_node->bookId = bId; new_node-
>duration = dur; new_node->rollNumber =  rollNo; 
new_node->mobileNumber = mobileNo;   
4. Thêm nút vào danh sách: 
if (start == NULL) { // Nếu danh sách rỗng 
start = new_node; new_node->next = 
NULL; } else { // Nếu danh sách không  rỗng   ptr = start; 
 while (ptr->next != NULL) { // Duyệt đến cuối danh sách  ptr = ptr->next;   } 
 ptr->next = new_node; // Thêm nút mới vào cuối   new_node->next = NULL;  }   
5. Cập nhật tổng số sách: 
total++; // Tăng biến đếm tổng số sách đã mượn printf("\n\t\t*****  Da tao ban ghi! *****\n");     
3.4. Hiển thị danh sách 
Chức năng hiển thị danh sách được triển khai trong hàm displayRecords():  
struct details *displayRecords() { struct  details *ptr;        lOMoAR cPSD| 60729183  
if (start == NULL) { printf("\t** Khong co ban  ghi de hien thi **\n");  } else { ptr  = start;  printf("\t\t\t 
________________________________________________________________________ 
________________________________________\n"); printf("\t\t\t| MA SACH\t| THOI 
GIAN MUON |\t NGAY MUON |\t Ten nganh | So the\t |\tSo dien thoai |\n"); 
printf("\t\t\t|_______________|____________________|________________|__________ 
_______|________________|_______________________|\n");    while (ptr != NULL) { 
printf("\t\t\t|%d\t | %d ngay\t |\t %s | %s \t| %d\t | %lld\t |\n", 
ptr->bookId, ptr->duration, __DATE__, ptr->branchName, ptr->rollNumber, ptr-  >mobileNumber); 
printf("\t\t\t|_______________|____________________|________________|__________ 
_______|________________|_______________________|\n"); ptr  = ptr->next; 
} } printf("\n\t\t\t\t\t\t******* Tong so sach da muon: %d *******\n",  total); return start;  }   
3.5. Thêm vào đầu danh sách 
Hiện tại chương trình chưa triển khai thêm vào đầu danh sách, nhưng có thể bổ sung  như sau:  
struct details *insertAtBeginning(struct details *start) { struct details 
*new_node = (struct details *)malloc(sizeof(struct details));        lOMoAR cPSD| 60729183  
 // Nhập dữ liệu cho new_node (tương tự createRecord)     if (start == NULL) {  start = new_node;  new_node->next = NULL;   } else { new_node- >next = start; start =  new_node; 
 } total++; printf("\n\t\t***** Da them vao dau danh 
sach! *****\n"); return start;  }     
3.6. Chèn vào cuối danh sách 
Chức năng này đã được triển khai trong hàm createRecord() khi thêm bản ghi mới:  
// Phần code trong hàm createRecord()  if (start == NULL) { start =  new_node; new_node->next =  NULL;  } else {  ptr = start; 
 while (ptr->next != NULL) {  ptr = ptr->next;   } 
 ptr->next = new_node; // Thêm vào cuối danh sách new_node- >next = NULL;  }        lOMoAR cPSD| 60729183  
3.7. Xóa sách theo mã sách 
Đã triển khai trong hàm deleteRecord():  
struct details *deleteRecord() { 
struct details *ptr, *prePtr, *postPtr;  int bId; int noBook;   
 printf("Nhap ma sach can tra: ");  scanf("%d", &bId);   
 // ... [phần code xử lý xóa]     return start;  }   
3.8. Tìm kiếm theo mã sách 
int search(int bId) { struct  details *ptr = start; while  (ptr != NULL) { if (ptr- >bookId == bId) {  return ptr->bookId;   } ptr =  ptr->next; }  return -1; }   
3.9. Thoát chương trình  // Trong menu chính case 3: 
 return 0; // Thoát chương trình      lOMoAR cPSD| 60729183          
CHƯƠNG 4: MÃ NGUỒN CHƯƠNG TRÌNH  4.1. Mã nguồn 
// He thong quan ly thu vien    #include  #include  #include   
struct details // Luu tru thong tin khi tao ban ghi muon sach 
{ char branchName[100]; // Ten nganh/chuyen  nganh 
 int bookId; // ID sach int duration; 
// Thoi gian muon (ngay) int rollNumber; // 
So the sinh vien long long int mobileNumber; // 
So dien thoai struct details *next; // Con tro toi  node tiep theo 
}; struct details *start =  NULL;   
struct details *createRecord(); // Tao ban ghi muon sach moi 
struct details *deleteRecord(); // Xoa ban ghi khi tra sach struct 
details *displayRecords(); // Hien thi tat ca ban ghi struct details 
*findRecord(); // Tim ban ghi theo so the sinh vien        lOMoAR cPSD| 60729183  
int search(); // Kiem tra sach da duoc muon chua int 
noElementSearch(); // Kiem tra sach chua duoc muon int 
noRollSearch(); // Kiem tra sinh vien chua muon sach  nao    struct node 
{ char adminPassword[30]; // Luu mat khau  admin 
}; struct node *start2 =  NULL;   
struct node *changePassword(); // Thay doi mat khau admin   
int total = 0; // Theo doi tong so sach da muon (ban dau la 0)   
int main() { int choice; // Lua chon trong menu 
admin int option; // Lua chon o trang dang nhap 
int studentRollNumber; // So the sinh vien char 
password[30]; // Mat khau nhap vao struct node 
*pass_node; // Con tro toi node chua mat khau   
 pass_node = (struct node *)malloc(sizeof(struct node)); // Tao node cho mat khau 
strcpy(pass_node->adminPassword, "thien123"); // Mat khau mac dinh        printf("\n\t\t\t\t 
====================================================\n"); 
 printf("\t\t\t\t CHAO MUNG DEN THU VIEN TRUNG TAM \n");      lOMoAR cPSD| 60729183       printf("\t\t\t\t 
====================================================\n\n");  do  {  login: 
 printf("\t\t\t\t\t _______________________________\n"); // Trang dang nhap 
printf("\t\t\t\t\t| DANG NHAP |\n"); 
printf("\t\t\t\t\t|_______________________________|\n"); 
 printf("\t\t\t\t\t| 1- Quan tri vien |\n"); 
 printf("\t\t\t\t\t|_______________________________|\n"); 
 printf("\t\t\t\t\t| 2- Sinh vien |\n"); 
 printf("\t\t\t\t\t|_______________________________|\n"); 
 printf("\t\t\t\t\t| 3- Thoat |\n"); 
 printf("\t\t\t\t\t|_______________________________|\n");   
 printf("\n\nNhap lua chon: ");  scanf("%d", &option);     switch (option)   {   case  1: 
 system("cls"); // Xoa man hinh 
printf("\nNhap mat khau: "); scanf("%s",  &password);   
 if (strcmp(password, pass_node->adminPassword) == 0) // Kiem tra mat khau      lOMoAR cPSD| 60729183    {   system("cls"); 
 printf("\n\t\t\t\t =================================\n"); 
printf("\t\t\t\t CHAO MUNG \n"); 
 printf("\t\t\t\t =================================\n");   
 printf("\t\t\t\t _______________________________________\n"); // Menu  admin 
 printf("\t\t\t\t| MENU QUAN TRI |\n"); 
printf("\t\t\t\t|_______________________________________|\n"); 
printf("\t\t\t\t| 1-Tao ban ghi muon sach |\n"); 
printf("\t\t\t\t|_______________________________________|\n"); 
printf("\t\t\t\t| 2-Xoa ban ghi tra sach |\n"); 
printf("\t\t\t\t|_______________________________________|\n"); 
printf("\t\t\t\t| 3-Hien thi tat ca ban ghi |\n"); 
printf("\t\t\t\t|_______________________________________|\n"); 
 printf("\t\t\t\t| 4-Doi mat khau |\n"); 
 printf("\t\t\t\t|_______________________________________|\n"); 
 printf("\t\t\t\t| 5-Thoat |\n"); 
 printf("\t\t\t\t|_______________________________________|\n");    do   { 
 printf("\n\nNhap lua chon: "); 
scanf("%d", &choice); printf("\n");     switch (choice)      lOMoAR cPSD| 60729183    {  case 1:   start = createRecord();   break;   case 2:  start = deleteRecord();  break;   case 3:  start = displayRecords();  break;   case  4: 
 start2 = changePassword(pass_node);   
 if (strcmp(pass_node->adminPassword, "thien123") != 0 || 
strcmp(pass_node->adminPassword, "thien123") == 0)   { 
 goto login; // Quay lai trang dang nhap sau khi doi mat khau   }    break;   case 5:  system("cls");  break;   default: 
 printf("\nLua chon khong hop le\n");   }      lOMoAR cPSD| 60729183      } while (choice != 5);   } else {  system("cls");  printf("Sai mat khau\n");   }    break;   case  2:   system("cls"); 
 printf("\n\t\t\t\t\t ===============================\n"); 
printf("\t\t\t\t\t CHAO MUNG \n"); 
 printf("\t\t\t\t\t ===============================\n\n");   
 printf("\t\t\t\t\t __________________________________\n"); // Menu sinh vien 
printf("\t\t\t\t\t| 1- Xem ban ghi muon sach |\n"); 
printf("\t\t\t\t\t|__________________________________|\n"); 
 printf("\t\t\t\t\t| 2- Dang xuat |\n"); 
 printf("\t\t\t\t\t|__________________________________|\n");   do   { 
 printf("\n\nNhap lua chon: "); 
 scanf("%d", &studentRollNumber);  switch (studentRollNumber)   { case  1: