Project Overview
Every book in the library is a struct holding its ID, title, author, and issue status. The whole library is just an array of these structs โ the rest of the program is functions that read or update that array.
- Display All Books โ prints a formatted table of the full catalog
- Issue a Book โ assigns a book to a member and starts a day counter
- Return a Book โ calculates any overdue fine and frees the book
- Search Book โ looks up a book by its ID
- Save to File โ writes the full catalog to a text file for persistence
| Concept used | Where |
|---|---|
| struct | Book record: ID, title, author, status, borrower, days issued |
| Arrays | Book library[TOTAL_BOOKS] holds the entire catalog |
| Functions | One function per menu operation โ keeps main() clean |
| switch-case | Routes the user's menu choice to the right function |
| File I/O | fopen/fprintf to persist catalog data |
| Conditional fine logic | Overdue calculation in returnBook() |
Book Struct & Catalog Initialization
Every book is described by one Book struct. The catalog is a fixed-size array โ TOTAL_BOOKS makes it easy to resize later. initLibrary() pre-loads 5 books so the program has data to work with immediately, and a due period of 14 days before fines start.
#include <stdio.h> #include <string.h> #include <stdlib.h> #define TOTAL_BOOKS 5 #define DUE_DAYS 14 #define FINE_PER_DAY 5.0 typedef struct { int id; char title[50]; char author[40]; int isIssued; char issuedTo[40]; int daysIssued; // how many days it has been out } Book; Book library[TOTAL_BOOKS]; // the entire catalog lives in this array void initLibrary() { char *titles[] = {"The C Programming Language", "Clean Code", "Data Structures Basics", "Algorithms 101", "Operating Systems"}; char *authors[] = {"K&R", "R. Martin", "A. Verma", "T. Cormen", "A. Silberschatz"}; for (int i = 0; i < TOTAL_BOOKS; i++) { library[i].id = 1001 + i; strcpy(library[i].title, titles[i]); strcpy(library[i].author, authors[i]); library[i].isIssued = 0; strcpy(library[i].issuedTo, "-"); library[i].daysIssued = 0; } }
time.h to record actual issue/due dates. Here, the user enters the number of days the book has been out at return time, which is enough to demonstrate the fine logic without extra date-handling complexity.Display, Search & Issue a Book
findBookIndex() is the shared helper โ it turns a book *ID* the user types into an array *index*. Both issuing and searching call it before touching any data, exactly like the room lookup in the Hotel project.
void displayBooks() { printf("\n%-6s %-28s %-16s %-10s %-12s\n", "ID", "Title", "Author", "Status", "Issued To"); for (int i = 0; i < TOTAL_BOOKS; i++) { printf("%-6d %-28s %-16s %-10s %-12s\n", library[i].id, library[i].title, library[i].author, library[i].isIssued ? "Issued" : "Available", library[i].issuedTo); } } int findBookIndex(int id) { for (int i = 0; i < TOTAL_BOOKS; i++) if (library[i].id == id) return i; return -1; // not found } void issueBook() { int id; char name[40]; printf("Enter book ID to issue: "); scanf("%d", &id); int idx = findBookIndex(id); if (idx == -1) { printf("Book not found.\n"); return; } if (library[idx].isIssued) { printf("Book already issued.\n"); return; } printf("Enter member name: "); scanf(" %[^\n]", name); // allows full names with spaces library[idx].isIssued = 1; strcpy(library[idx].issuedTo, name); library[idx].daysIssued = 0; printf("\"%s\" issued to %s.\n", library[idx].title, name); } void searchBook() { int id; printf("Enter book ID to search: "); scanf("%d", &id); int idx = findBookIndex(id); if (idx == -1) { printf("Book not found.\n"); return; } printf("[%d] %s by %s | %s | Issued to: %s\n", library[idx].id, library[idx].title, library[idx].author, library[idx].isIssued ? "Issued" : "Available", library[idx].issuedTo); }
Return with Fine Calculation & File Saving
Returning a book asks how many days it was actually kept, compares that against the DUE_DAYS limit, and only charges a fine for the days over the limit. saveToFile() writes the whole catalog as CSV lines, just like the Hotel project's room export.
void returnBook() { int id, daysKept; printf("Enter book ID to return: "); scanf("%d", &id); int idx = findBookIndex(id); if (idx == -1) { printf("Book not found.\n"); return; } if (!library[idx].isIssued) { printf("This book was not issued.\n"); return; } printf("Enter number of days kept: "); scanf("%d", &daysKept); printf("\n----- Return Receipt -----\n"); printf("Book : %s\n", library[idx].title); printf("Member: %s\n", library[idx].issuedTo); printf("Days kept: %d (allowed: %d)\n", daysKept, DUE_DAYS); if (daysKept > DUE_DAYS) { int overdueDays = daysKept - DUE_DAYS; float fine = overdueDays * FINE_PER_DAY; printf("Overdue by %d day(s) -> Fine: Rs %.2f\n", overdueDays, fine); } else { printf("Returned on time. No fine.\n"); } // free the book for the next member library[idx].isIssued = 0; strcpy(library[idx].issuedTo, "-"); library[idx].daysIssued = 0; } void saveToFile() { FILE *fp = fopen("library_data.txt", "w"); if (!fp) { printf("Error saving file.\n"); return; } for (int i = 0; i < TOTAL_BOOKS; i++) { fprintf(fp, "%d,%s,%s,%d,%s\n", library[i].id, library[i].title, library[i].author, library[i].isIssued, library[i].issuedTo); } fclose(fp); printf("Data saved to library_data.txt\n"); }
fine = max(0, daysKept - DUE_DAYS) * FINE_PER_DAY. The if check does the "max(0, ...)" part manually โ no fine is ever charged for returning on time or early.The Main Menu
Same pattern as every project in this series: main() stays small, looping with a do-while and routing choices with switch. Keeping main() thin makes the whole program easier to read and extend.
int main() { initLibrary(); int choice; do { printf("\n===== LIBRARY MANAGEMENT SYSTEM =====\n"); printf("1. Display All Books\n"); printf("2. Issue a Book\n"); printf("3. Return a Book\n"); printf("4. Search Book\n"); printf("5. Save Data to File\n"); printf("6. Exit\n"); printf("Enter choice: "); scanf("%d", &choice); switch (choice) { case 1: displayBooks(); break; case 2: issueBook(); break; case 3: returnBook(); break; case 4: searchBook(); break; case 5: saveToFile(); break; case 6: printf("Exiting... Goodbye!\n"); break; default: printf("Invalid choice.\n"); } } while (choice != 6); return 0; }
===== LIBRARY MANAGEMENT SYSTEM ===== 1. Display All Books 2. Issue a Book 3. Return a Book 4. Search Book 5. Save Data to File 6. Exit Enter choice: 1 ID Title Author Status Issued To 1001 The C Programming Language K&R Available - 1002 Clean Code R. Martin Available - 1003 Data Structures Basics A. Verma Available - 1004 Algorithms 101 T. Cormen Available - 1005 Operating Systems A. Silberschatz Available - Enter choice: 2 Enter book ID to issue: 1003 Enter member name: Ananya Rao "Data Structures Basics" issued to Ananya Rao. Enter choice: 3 Enter book ID to return: 1003 Enter number of days kept: 20 ----- Return Receipt ----- Book : Data Structures Basics Member: Ananya Rao Days kept: 20 (allowed: 14) Overdue by 6 day(s) -> Fine: Rs 30.00 Enter choice: 6 Exiting... Goodbye!
Ways to Extend This Project
Once the base version compiles and runs, these upgrades each reuse a concept you've already covered in earlier lessons:
- Load from file on startup โ read
library_data.txtwithfscanfso the catalog survives between runs - Dynamic catalog size โ replace the fixed array with
malloc-allocated memory sized from user input - Waitlist per book โ a linked list of members waiting for a currently-issued book
- Search by title โ linear search with
strstrfor partial title matches - Sort catalog by title or author โ plug in any algorithm from the Sorting lesson
- Real due dates โ use
time.hto store actual issue/due dates instead of a manually entered day count
| Extension | Concept it reuses |
|---|---|
| Persistent load/save | File I/O lesson |
| Dynamic catalog | Dynamic memory (malloc/realloc) lesson |
| Waitlist per book | Linked Lists lesson |
| Sort by title/author | Sorting Algorithms lesson |
Project Checklist
- I understand the Book struct and what each field stores
- I can explain how findBookIndex() connects book ID to array index
- I can trace issueBook() end to end
- I understand the overdue fine calculation in returnBook()
- I know why the book is reset after return
- I understand how saveToFile() writes each book as a CSV line
- I can trace the do-while + switch main menu loop
- I compiled and ran the full program myself
- I picked at least one extension to try next