OnlineCBT Logo OnlineCBT
C Tutorial
C · LESSON 19

C Project: Student Management System

By Ratan Updated: 15 Oct 2026

Build a console-based student records management program with file persistence in C.

Level: Beginner to Advanced
Duration: ~60 Mins Deep-Dive

Build a small student register

This project combines structures, arrays, functions, strings and validated input. The first working version adds students, lists them and searches by roll number. It deliberately keeps records in memory so you can debug the program before adding file persistence.

Requirements and invariants

  • Store at most 50 students. A full register must reject another addition.
  • Use a positive, unique roll number, a non-empty name of at most 39 bytes and marks from 0 through 100.
  • Reject malformed input without using an uninitialized value.
  • Searching must not modify the register. Exiting this version discards the records.

Complete starter implementation

#include 
#include 
#include 
#include 
#include 
#include 

enum { CAPACITY = 50, NAME_SIZE = 40 };
struct Student { int roll; char name[NAME_SIZE]; int marks; };

/* 1: complete line, 0: EOF/error, -1: line too long */
static int read_line(char *out, int capacity) {
    if (fgets(out, capacity, stdin) == NULL) return 0;
    char *newline = strchr(out, '\n');
    if (newline != NULL) { *newline = '\0'; return 1; }
    int ch = getchar();
    if (ch == '\n' || ch == EOF) return 1;
    while ((ch = getchar()) != '\n' && ch != EOF) { }
    return -1;
}
static int read_number(const char *prompt, int low, int high, int *out) {
    char line[80];
    fputs(prompt, stdout);
    int status = read_line(line, (int)sizeof line);
    if (status != 1) return status == 0 ? -1 : 0;
    errno = 0;
    char *end;
    long value = strtol(line, &end, 10);
    if (end == line || errno == ERANGE) return 0;
    while (isspace((unsigned char)*end)) ++end;
    if (*end != '\0' || value < low || value > high) return 0;
    *out = (int)value;
    return 1;
}
static int find_roll(const struct Student students[], size_t count, int roll) {
    for (size_t i = 0; i < count; ++i) {
        if (students[i].roll == roll) return (int)i;
    }
    return -1;
}
int main(void) {
    struct Student students[CAPACITY];
    size_t count = 0;
    for (;;) {
        puts("1 Add | 2 List | 3 Find | 0 Exit");
        int choice;
        int status = read_number("Choice: ", 0, 3, &choice);
        if (status == -1) break;
        if (status == 0) { puts("Enter 0, 1, 2 or 3."); continue; }
        if (choice == 0) break;
        if (choice == 1) {
            if (count == CAPACITY) { puts("Register full."); continue; }
            struct Student candidate;
            status = read_number("Roll: ", 1, INT_MAX, &candidate.roll);
            if (status == -1) break;
            if (status == 0) { puts("Invalid roll."); continue; }
            if (find_roll(students, count, candidate.roll) != -1) {
                puts("Roll already exists."); continue;
            }
            fputs("Name: ", stdout);
            status = read_line(candidate.name, NAME_SIZE);
            if (status == 0) break;
            if (status == -1 || candidate.name[0] == '\0') {
                puts("Name is empty or too long."); continue;
            }
            status = read_number("Marks: ", 0, 100, &candidate.marks);
            if (status == -1) break;
            if (status == 0) { puts("Marks must be 0 to 100."); continue; }
            students[count++] = candidate;
            puts("Student added.");
        } else if (choice == 2) {
            if (count == 0) puts("Register is empty.");
            for (size_t i = 0; i < count; ++i) {
                printf("%d | %s | %d\n", students[i].roll,
                       students[i].name, students[i].marks);
            }
        } else {
            int roll;
            status = read_number("Find roll: ", 1, INT_MAX, &roll);
            if (status == -1) break;
            if (status == 0) { puts("Invalid roll."); continue; }
            int index = find_roll(students, count, roll);
            if (index == -1) puts("Not found.");
            else printf("%s | %d\n", students[index].name,
                        students[index].marks);
        }
    }
    puts("Session ended; records were in memory only.");
    return 0;
}

Run and trace

Save as students.c and build with gcc -std=c17 -Wall -Wextra -pedantic students.c -o students. Choose 1, enter roll 101, name Asha and marks 82. Choose 2: expect 101 | Asha | 82. Choose 3 and roll 101: expect Asha | 82. Repeating roll 101 must report that it already exists.

Why the input helpers matter

read_line detects overlong lines and drains the remaining input. read_number uses strtol, checks conversion, overflow, trailing non-whitespace and the permitted range. A temporary candidate is added only after all fields pass validation, so a half-completed form cannot corrupt the stored register. The name rule is intentionally minimal; extend it to reject whitespace-only names if that is required.

Test checklist

Test listing an empty register, duplicate rolls, marks -1 and 101, letters instead of a number, an overlong name, missing search results and end-of-file during entry. Count must increase only after a successful addition. Names are byte-limited; supporting arbitrary Unicode text needs a clearer encoding and length policy.

Extend in small stages

  1. Add an update-marks operation using find_roll and the same marks validator.
  2. Delete by shifting following records left and decrementing count exactly once.
  3. Save a documented text format and load it with the same validation rules; reject duplicate or malformed records. Escape separators in names.
  4. For reliable persistence, write a new temporary file, check all writes and close errors, then replace the old file using the platform's documented facilities. Do not truncate the only copy before a successful save.

Project boundary: this is a learning console program, not a production student-information system. Authentication, authorization, personal-data protection, concurrent edits and backups require additional design.

📝 Live Lesson Practice

HTML/CSS JavaScript Python C++ C PHP
⌨️ Practice Inputs (लाइव इनपुट भरें) (खाली होने पर RED, भरने पर GREEN underline)
💻 Code Editor (Monaco VS Code Engine)
👀 Live Preview
Address Contact

+91 7877547686

E-mail

onlinecbtportal@gmail.com

Helpline Number

+91 7877547686


Click To Download
Get it on Google Play

ऐप डाउनलोड करने
के लिए Google Play पर
उपलब्ध है

WhatsApp Chat