Project Progress
0%
Capstone Project  ·  Core C Only — No Data Structures

Student Result Management System

One deliberately simple project that touches every core C fundamental — files, pointers, loops, structs, strings, if-else, continue, break, storage classes, arrays, and functions — with no linked lists, stacks, or trees involved.

Struct + const + global
Pointer + static + if-else
break + continue + strings
File I/O
Main menu
📖

Project Overview & Topic Map

Every fundamental concept below appears in this ONE program — nothing here needs a linked list, stack, queue, or tree. The goal is breadth across the basics, not a new data structure.

ConceptWhere it appears
Structuresstruct Student — roll, name, marks, average, grade
Arraysstudents[] array of structs; marks[3] inside each struct
PointersaddStudent() writes through Student *s
Stringsname[40], read with %[^\n]
if-elseGrade calculation ladder (A/B/C/F)
breakStops searchByRoll() the moment a match is found
continueSkips counting a failed student as "pass" in the summary loop
Storage classesconst pass mark, static call counter, global studentCount
FilessaveToFile() writes all records with fprintf
FunctionsOne function per operation, called from a menu
part 1
1

Struct, Global Array & const (Storage/Qualifier Basics)

Data model + scope

PASS_MARK is declared const — its value can never change after this line, protecting the pass threshold from accidental edits anywhere else in the file. students[] and studentCount are global — declared outside any function, so every function in the file can see and use them directly.

Part 1 · student_system.c — structs & globals
student_system.c
C
#include <stdio.h>
#include <string.h>

#define MAX_STUDENTS 5
const float PASS_MARK = 40.0;   // cannot be changed anywhere after this

typedef struct {
    int   roll;
    char  name[40];
    float marks[3];    // 3 subjects
    float average;
    char  grade;
} Student;

Student students[MAX_STUDENTS];   // global array — visible to every function below
int studentCount = 0;         // global — tracks how many slots are filled
💡 Global vs local, in one sentence: a global variable is declared outside every function and lives for the whole program; a local variable is declared inside a function and only exists while that function is running.
part 2
2

Adding a Student — Pointer, static, and if-else

The busiest function in the project

s is a pointer to the new student's slot in the array — every field is written through s->, directly into the real array, not a copy. addCallCount is static: unlike a normal local variable, it keeps its value between calls instead of resetting to 0 every time the function runs.

Part 2 · student_system.c — addStudent()
student_system.c
C
void addStudent() {
    static int addCallCount = 0;   // persists across every call, private to this function
    addCallCount++;

    if (studentCount >= MAX_STUDENTS) {
        printf("Student list full.\n");
        return;
    }

    Student *s = &students[studentCount];   // pointer to the new slot

    printf("Enter roll number: ");
    scanf("%d", &s->roll);
    printf("Enter name: ");
    scanf(" %[^\n]", s->name);   // reads a full name with spaces

    float total = 0;
    for (int i = 0; i < 3; i++) {
        printf("Enter marks for subject %d: ", i + 1);
        scanf("%f", &s->marks[i]);
        total += s->marks[i];
    }
    s->average = total / 3;

    if (s->average >= 90)
        s->grade = 'A';
    else if (s->average >= 75)
        s->grade = 'B';
    else if (s->average >= PASS_MARK)
        s->grade = 'C';
    else
        s->grade = 'F';

    studentCount++;
    printf("Student added. (addStudent called %d time(s) so far)\n", addCallCount);
}
⚠️ static vs global — don't confuse them. Both "remember" their value, but addCallCount stays private to addStudent() — no other function can see or accidentally modify it, unlike studentCount which any function in the file can touch.
part 3
3

Search & Summary — break, continue, and Strings

Loop control in action

searchByRoll() uses break the instant it finds a match — continuing to check the rest of the array would be wasted work. passFailSummary() uses continue to skip the "pass" counter for failing students without needing an extra else block.

Part 3 · student_system.c — search & summary
student_system.c
C
void searchByRoll() {
    int roll, found = 0;
    printf("Enter roll number to search: ");
    scanf("%d", &roll);

    for (int i = 0; i < studentCount; i++) {
        if (students[i].roll == roll) {
            printf("Found: %s | Average: %.2f | Grade: %c\n",
                   students[i].name, students[i].average, students[i].grade);
            found = 1;
            break;   // stop immediately — no need to keep scanning
        }
    }
    if (!found)
        printf("Roll number not found.\n");
}

void passFailSummary() {
    int pass = 0, fail = 0;

    for (int i = 0; i < studentCount; i++) {
        if (students[i].grade == 'F') {
            fail++;
            continue;   // skip the pass++ below, move to the next student
        }
        pass++;
    }
    printf("Passed: %d | Failed: %d\n", pass, fail);
}
💡 %[^\n] and comparing names: since name is a plain char array, comparing two names for equality would use strcmp(students[i].name, target) == 0 — never == directly, which would compare addresses instead of the actual text.
part 4
4

Saving Records to a File

Persisting the array

Same file-writing pattern as the Hotel, Library, Hospital, and Banking projects — loop through the array, write one CSV line per record with fprintf.

Part 4 · student_system.c — saveToFile()
student_system.c
C
void saveToFile() {
    FILE *fp = fopen("students.txt", "w");
    if (!fp) { printf("Error opening file.\n"); return; }

    for (int i = 0; i < studentCount; i++) {
        fprintf(fp, "%d,%s,%.2f,%c\n",
                students[i].roll, students[i].name,
                students[i].average, students[i].grade);
    }
    fclose(fp);
    printf("Saved to students.txt\n");
}

void displayAll() {
    printf("\n%-6s %-16s %-10s %-6s\n", "Roll", "Name", "Average", "Grade");
    for (int i = 0; i < studentCount; i++) {
        printf("%-6d %-16s %-10.2f %-6c\n",
               students[i].roll, students[i].name, students[i].average, students[i].grade);
    }
}
part 5
5

The Main Menu

do-while + switch

Same thin main() pattern as the other projects — a do-while loop with a switch routing each choice to the right function.

Part 5 · student_system.c — main()
student_system.c
C
int main() {
    int choice;

    do {
        printf("\n===== STUDENT RESULT MANAGEMENT =====\n");
        printf("1. Add Student\n");
        printf("2. Display All\n");
        printf("3. Search by Roll\n");
        printf("4. Pass/Fail Summary\n");
        printf("5. Save to File\n");
        printf("6. Exit\n");
        printf("Enter choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1: addStudent();       break;
            case 2: displayAll();       break;
            case 3: searchByRoll();     break;
            case 4: passFailSummary(); break;
            case 5: saveToFile();       break;
            case 6: printf("Exiting... Goodbye!\n"); break;
            default: printf("Invalid choice.\n");
        }
    } while (choice != 6);

    return 0;
}
terminal — sample session
output
===== STUDENT RESULT MANAGEMENT =====
1. Add Student
2. Display All
3. Search by Roll
4. Pass/Fail Summary
5. Save to File
6. Exit
Enter choice: 1
Enter roll number: 101
Enter name: Aditi Sharma
Enter marks for subject 1: 88
Enter marks for subject 2: 92
Enter marks for subject 3: 79
Student added. (addStudent called 1 time(s) so far)

Enter choice: 1
Enter roll number: 102
Enter name: Rohan Gupta
Enter marks for subject 1: 30
Enter marks for subject 2: 25
Enter marks for subject 3: 35
Student added. (addStudent called 2 time(s) so far)

Enter choice: 2

Roll   Name             Average    Grade
101    Aditi Sharma     86.33      B
102    Rohan Gupta      30.00      F

Enter choice: 4
Passed: 1 | Failed: 1

Enter choice: 6
Exiting... Goodbye!
extend it

Ways to Extend This Project

Every upgrade below still avoids data structures, staying within the same fundamentals-first spirit:

  • Load from file on startup — read students.txt back with fscanf
  • Search by name — loop + strcmp() instead of comparing roll numbers
  • Update a record — find by roll (reusing the search pattern), then overwrite fields through a pointer
  • More subjects — increase the marks[3] array size and adjust the average calculation
  • extern practice — split the file into main.c and student.c, declaring shared globals with extern

Project Checklist

  • I understand the Student struct and the global students[] array
  • I can explain why PASS_MARK is declared const
  • I can trace addStudent() writing through the pointer s
  • I understand how static addCallCount differs from a normal local variable
  • I can trace the if-else grade ladder
  • I understand why break stops searchByRoll() immediately
  • I understand why continue skips the pass++ line for failing students
  • I understand how saveToFile() writes each student as a CSV line
  • I compiled and ran the full program myself