Why does this system exist?
A department coordinator repeatedly needs to register students, view the current list, locate one student, correct information and remove discontinued records. Paper registers and parallel arrays make these operations inconsistent. Our C application creates one authoritative record format and stores it beyond the current execution.
Actors and use cases
Coordinator
Adds, updates, searches and deletes records.
Student
Provides ID, name, branch and CGPA.
System
Validates, persists and reports results clearly.
Scope boundary
This educational version is a single-user command-line system. It does not include authentication, concurrent access or a network database. Those omissions are deliberate: the focus is structures, modular functions and reliable file replacement.
Functional and quality requirements
FR-1 Add
Accept a unique positive ID, non-empty name and branch, and CGPA from 0.00 to 10.00.
FR-2 List
Read all stored records and print an aligned table plus total count.
FR-3 Search
Scan records by ID and show exactly one matching student.
FR-4 Update
Replace the non-key details of an existing student without changing the ID.
FR-5 Delete
Remove exactly one matching record and retain every other record.
FR-6 Exit
End cleanly without leaving files open or temporary files behind.
Non-functional requirements
- Correctness: reject duplicates and invalid CGPA values.
- Persistence: records remain available to later operations in the same environment.
- Maintainability: one function owns one responsibility.
- Recoverability: update/delete build a temporary replacement before touching the original.
- Usability: prompts explain the expected range and errors explain the cause.
Represent one student as one structure
Student = { id: int, name: char[60], branch: char[20], cgpa: float }| Field | Purpose | Rule | Why this type? |
|---|---|---|---|
| id | Stable lookup key | > 0 and unique | Integer comparison is simple and exact. |
| name | Student identity | Non-empty, up to 59 chars | Fixed array keeps the binary record size constant. |
| branch | Academic programme | Non-empty, up to 19 chars | Short controlled text fits a fixed array. |
| cgpa | Academic performance | 0.0–10.0 | Decimal values require floating-point storage. |
Binary-file representation
fwrite(&s, sizeof s, 1, file) stores the complete structure as a fixed-size record. This makes sequential reading easy, but the file is tied to the structure layout and compiler representation. For portable data exchange, CSV or a database is better.
How data moves through the system
| Module | Responsibility | Must not do |
|---|---|---|
| readInt / readFloat / readLine | Collect clean input | Make record decisions |
| validStudent | Enforce domain constraints | Read or write files |
| idExists | Prevent duplicate keys | Modify records |
| add/list/search | Perform direct CRUD operations | Own the menu loop |
| update/delete | Create safe replacement file | Overwrite source in place |
| main/menu | Coordinate user choices | Contain file-processing details |
CRUD logic before code
Add algorithm
- Read the proposed ID and scan the file for a duplicate.
- Read name, branch and CGPA.
- Validate every field as one complete Student object.
- Open the binary file in append mode.
- Write exactly one structure and verify the write count.
Search algorithm
- Open the file in read-binary mode.
- Read one structure at a time using
fread. - Compare its ID with the target; return immediately on a match.
- If end-of-file is reached, report “not found”.
Safe update/delete pattern
Compiler-ready C11 program
Read the function boundaries first. Then copy the code, open the CodeBhavya compiler and test one operation at a time.
Loading source…Reading guide
Start at main
Understand the endless menu loop and switch dispatch.
Follow one operation
Trace Add from input to validation to fwrite.
Compare mutation paths
Notice why update/delete need a temporary file but search does not.
Trace: adding ID 1001 and searching it
- User selects Add student.
- readInt stores ID 1001.
- Uniqueness check passes.
- Text fields are collected with fgets.
- CGPA is read and full object is validated.
- File opens in append-binary mode.
- Student 1001 is persisted.
- User chooses Search.
- Matching record is found.
- Search completes successfully.
Press Next to begin.
Test normal, boundary and failure paths
Test 1 — Valid add and list
1 1001 Bhavya Rao CSE-AIML 8.70 2 6Expected: “Student added successfully”, one aligned row, total records 1.
Test 2 — Duplicate ID
Test 3 — CGPA boundaries
Test 4 — Search missing ID
Test 5 — Update cancellation
Test 6 — Delete only record
Cost as the record count grows
| Operation | Time | Extra space | Reason |
|---|---|---|---|
| Add with duplicate check | O(n) | O(1) | Existing IDs are scanned first. |
| List | O(n) | O(1) | Every record is read once. |
| Search | O(n) | O(1) | Sequential file has no index. |
| Update | O(n) | O(1)* | All records are copied; disk temp is O(n). |
| Delete | O(n) | O(1)* | All retained records are copied. |
*RAM usage is constant because one record is processed at a time; the temporary file requires O(n) disk space.
What makes this safer—and what remains
Controls included
- Input-type checks and buffer cleanup
- Duplicate ID prevention
- Full-object validation
- Every opened file is closed
- Update cancellation removes the temp file
- Immediate return after a successful search
Production improvements
- Use CSV/SQLite for portable records
- Lock files during concurrent access
- Write audit logs and backups
- Use authenticated roles
- Normalise branch values
- Use atomic rename strategy supported by the OS
Prove that you understand the system
Which operations require a temporary replacement file?
Why is Student ID not edited?
Extension challenges
- Add semester, email and placement-status fields; update validation and table formatting.
- Create a report of students with CGPA greater than a user-supplied threshold.
- Sort records by CGPA without changing the stored order.
- Export all records to readable CSV.
- Add a confirmation step before deletion.
Explain your design decisions
Why use a structure instead of parallel arrays?
A structure keeps all fields belonging to one student together. Passing, reading and writing one logical record becomes simpler, and indices cannot accidentally become misaligned across arrays.
Why use append mode for Add?
ab writes a new fixed-size record at the end without rewriting existing records. The duplicate scan happens before opening the append stream.
Why not update directly with fseek?
Fixed-size records can be updated in place, but a temporary-file approach unifies update and delete, is easier to reason about, and avoids leaving half-written record content after a failed operation.
What is the largest limitation of binary structure files?
The representation can change with compiler padding, field sizes and architecture. It is not a stable interchange format across unrelated systems.
How would you support fast search?
Maintain an in-memory hash index from ID to file offset, keep records sorted for binary search, or move persistence to an indexed database.
One program connects the complete C foundation
This system combines input handling, functions, structures, validation, switch-based control flow, sequential searching and persistent files. More importantly, it demonstrates an engineering habit: validate before mutation and preserve the original until the replacement is ready.
