In this lesson, we will build a simple Student Management System using C. This mini project combines many concepts learned throughout the course, including structures, arrays, functions, loops, conditions, strings, file handling, and menu-driven programming.
Our mini project will manage basic student information.
The program will store:
The application will use a menu so that the user can select different operations.
Our Student Management System will contain the following features:
A structure is suitable for storing different types of information about one student.
struct Student
{
int id;
char name[50];
float marks;
char grade;
};
Each student can now contain an ID, name, marks, and grade.
We can use an array of structures to store multiple students.
#define MAX_STUDENTS 100
struct Student students[MAX_STUDENTS];
int studentCount = 0;
The studentCount variable keeps track of how many students
are currently stored.
Our project uses several standard C library features.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
stdio.h is used for input/output and files,
stdlib.h provides general-purpose functions, and
string.h provides string functions.
We can create a separate function to determine a student's grade.
char calculateGrade(float marks)
{
if(marks >= 90)
return 'A';
else if(marks >= 75)
return 'B';
else if(marks >= 60)
return 'C';
else if(marks >= 40)
return 'D';
else
return 'F';
}
Marks should normally be between 0 and 100. We can validate the value before storing it.
if(marks < 0 || marks > 100)
{
printf("Invalid marks!\n");
}
Input validation helps prevent invalid data from entering the system.
The addStudent() function can collect information from the
user and store it in the array.
void addStudent(struct Student students[],
int *count)
{
if(*count >= MAX_STUDENTS)
{
printf("Student limit reached.\n");
return;
}
printf("Enter student ID: ");
scanf("%d", &students[*count].id);
printf("Enter student name: ");
scanf(" %49[^\n]", students[*count].name);
printf("Enter marks: ");
scanf("%f", &students[*count].marks);
students[*count].grade =
calculateGrade(students[*count].marks);
(*count)++;
printf("Student added successfully.\n");
}
The addStudent() function needs to update the original
student count. A pointer allows the function to modify the variable in
the calling function.
void addStudent(struct Student students[],
int *count)
The expression (*count)++ increases the original count.
A separate function can display the details of one student.
void displayStudent(struct Student s)
{
printf("ID : %d\n", s.id);
printf("Name : %s\n", s.name);
printf("Marks : %.2f\n", s.marks);
printf("Grade : %c\n", s.grade);
}
We can use a loop to display every student in the array.
void displayAll(struct Student students[],
int count)
{
int i;
if(count == 0)
{
printf("No students available.\n");
return;
}
for(i = 0; i < count; i++)
{
printf("\nStudent %d\n", i + 1);
displayStudent(students[i]);
}
}
We can search the array using the student's ID.
int findStudent(struct Student students[],
int count,
int id)
{
int i;
for(i = 0; i < count; i++)
{
if(students[i].id == id)
{
return i;
}
}
return -1;
}
Returning -1 means that the student was not found.
The search function can use findStudent() and display the
matching record.
void searchStudent(struct Student students[],
int count)
{
int id;
int index;
printf("Enter student ID: ");
scanf("%d", &id);
index = findStudent(students, count, id);
if(index == -1)
{
printf("Student not found.\n");
}
else
{
displayStudent(students[index]);
}
}
We can allow the user to update the marks of an existing student.
void updateMarks(struct Student students[],
int count)
{
int id;
int index;
float marks;
printf("Enter student ID: ");
scanf("%d", &id);
index = findStudent(students, count, id);
if(index == -1)
{
printf("Student not found.\n");
return;
}
printf("Enter new marks: ");
scanf("%f", &marks);
if(marks < 0 || marks > 100)
{
printf("Invalid marks.\n");
return;
}
students[index].marks = marks;
students[index].grade = calculateGrade(marks);
printf("Marks updated successfully.\n");
}
The project can save student information to a text file using
fopen().
FILE *file;
file = fopen("students.txt", "w");
if(file == NULL)
{
printf("Unable to open file.\n");
return;
}
Always check whether the file was opened successfully.
void saveStudents(struct Student students[],
int count)
{
FILE *file;
int i;
file = fopen("students.txt", "w");
if(file == NULL)
{
printf("Unable to open file.\n");
return;
}
for(i = 0; i < count; i++)
{
fprintf(file, "%d|%s|%.2f|%c\n",
students[i].id,
students[i].name,
students[i].marks,
students[i].grade);
}
fclose(file);
printf("Students saved successfully.\n");
}
We can also load previously saved records when the program starts.
void loadStudents(struct Student students[],
int *count)
{
FILE *file;
file = fopen("students.txt", "r");
if(file == NULL)
{
return;
}
while(*count < MAX_STUDENTS &&
fscanf(file, "%d|%49[^|]|%f|%c\n",
&students[*count].id,
students[*count].name,
&students[*count].marks,
&students[*count].grade) == 4)
{
(*count)++;
}
fclose(file);
}
A menu makes the application easier to use.
printf("\n===== Student Management =====\n");
printf("1. Add Student\n");
printf("2. Display Students\n");
printf("3. Search Student\n");
printf("4. Update Marks\n");
printf("5. Save Students\n");
printf("6. Exit\n");
printf("Enter choice: ");
The switch statement is suitable for processing menu choices.
switch(choice)
{
case 1:
addStudent(students, &studentCount);
break;
case 2:
displayAll(students, studentCount);
break;
case 3:
searchStudent(students, studentCount);
break;
default:
printf("Invalid choice.\n");
}
A do-while loop can keep displaying the menu until the user
chooses to exit.
do
{
printf("\n1. Add Student");
printf("\n2. Display Students");
printf("\n3. Search Student");
printf("\n4. Update Marks");
printf("\n5. Save Students");
printf("\n6. Exit");
printf("\nEnter choice: ");
scanf("%d", &choice);
} while(choice != 6);
switch(choice)
{
case 1:
addStudent(students, &studentCount);
break;
case 2:
displayAll(students, studentCount);
break;
case 3:
searchStudent(students, studentCount);
break;
case 4:
updateMarks(students, studentCount);
break;
case 5:
saveStudents(students, studentCount);
break;
case 6:
saveStudents(students, studentCount);
printf("Goodbye!\n");
break;
default:
printf("Invalid choice.\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STUDENTS 100
struct Student
{
int id;
char name[50];
float marks;
char grade;
};
char calculateGrade(float marks)
{
if(marks >= 90)
return 'A';
else if(marks >= 75)
return 'B';
else if(marks >= 60)
return 'C';
else if(marks >= 40)
return 'D';
else
return 'F';
}
int findStudent(struct Student students[],
int count,
int id)
{
int i;
for(i = 0; i < count; i++)
{
if(students[i].id == id)
return i;
}
return -1;
}
void addStudent(struct Student students[],
int *count)
{
float marks;
if(*count >= MAX_STUDENTS)
{
printf("Student limit reached.\n");
return;
}
printf("Enter ID: ");
scanf("%d", &students[*count].id);
printf("Enter name: ");
scanf(" %49[^\n]", students[*count].name);
printf("Enter marks: ");
scanf("%f", &marks);
if(marks < 0 || marks > 100)
{
printf("Invalid marks.\n");
return;
}
students[*count].marks = marks;
students[*count].grade = calculateGrade(marks);
(*count)++;
printf("Student added successfully.\n");
}
void displayStudent(struct Student s)
{
printf("\nID : %d\n", s.id);
printf("Name : %s\n", s.name);
printf("Marks : %.2f\n", s.marks);
printf("Grade : %c\n", s.grade);
}
void displayAll(struct Student students[],
int count)
{
int i;
if(count == 0)
{
printf("No students available.\n");
return;
}
for(i = 0; i < count; i++)
{
printf("\nStudent %d", i + 1);
displayStudent(students[i]);
}
}
void searchStudent(struct Student students[],
int count)
{
int id;
int index;
printf("Enter ID: ");
scanf("%d", &id);
index = findStudent(students, count, id);
if(index == -1)
{
printf("Student not found.\n");
}
else
{
displayStudent(students[index]);
}
}
void updateMarks(struct Student students[],
int count)
{
int id;
int index;
float marks;
printf("Enter ID: ");
scanf("%d", &id);
index = findStudent(students, count, id);
if(index == -1)
{
printf("Student not found.\n");
return;
}
printf("Enter new marks: ");
scanf("%f", &marks);
if(marks < 0 || marks > 100)
{
printf("Invalid marks.\n");
return;
}
students[index].marks = marks;
students[index].grade = calculateGrade(marks);
printf("Marks updated successfully.\n");
}
void saveStudents(struct Student students[],
int count)
{
FILE *file;
int i;
file = fopen("students.txt", "w");
if(file == NULL)
{
printf("Unable to open file.\n");
return;
}
for(i = 0; i < count; i++)
{
fprintf(file, "%d|%s|%.2f|%c\n",
students[i].id,
students[i].name,
students[i].marks,
students[i].grade);
}
fclose(file);
printf("Data saved successfully.\n");
}
int main()
{
struct Student students[MAX_STUDENTS];
int studentCount = 0;
int choice;
do
{
printf("\n\n===== STUDENT MANAGEMENT =====\n");
printf("1. Add Student\n");
printf("2. Display Students\n");
printf("3. Search Student\n");
printf("4. Update Marks\n");
printf("5. Save Students\n");
printf("6. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
switch(choice)
{
case 1:
addStudent(students, &studentCount);
break;
case 2:
displayAll(students, studentCount);
break;
case 3:
searchStudent(students, studentCount);
break;
case 4:
updateMarks(students, studentCount);
break;
case 5:
saveStudents(students, studentCount);
break;
case 6:
saveStudents(students, studentCount);
printf("Goodbye!\n");
break;
default:
printf("Invalid choice.\n");
}
} while(choice != 6);
return 0;
}
main().After completing the basic project, you can add more features.
These improvements can turn the mini project into a larger C application.
Now create your own improved Student Management System.
Your final version should include:
Try to divide the project into multiple files such as
main.c, student.c, and student.h.
This will give you practical experience with modular C programming.
switch is useful for menu-driven programs..c and .h files.Question: Which C feature is most suitable for storing different types of information about one student, such as ID, name, and marks?