Module 5 : Data Types (Struct, Enum, TypeDef) & File I/O
By the end of this module, students will be able to:
- Understand and implement user-defined data types using `struct`
- Utilize `enum` for creating readable constant sets
- Apply `typedef` to create type aliases for better code readability
- Perform file input/output operations in C
- Handle text and binary files effectively
- Design programs that persist data using files
- Combine structs with file I/O for data management systems
- 1. Introduction to User-Defined Data Types
- 2. Structures (struct)
- 3. Enumerations (enum)
- 4. Type Definitions (typedef)
- 5. File Input/Output
1. Introduction to User-Defined Data Types
1.1 Why User-Defined Types?
In previous modules, we learned about basic data types like int, float, char, etc. These are sufficient for simple programs, but real-world applications often require more complex data structures.
Example Problem: Suppose you want to store information about a student:
// Without user-defined types - difficult to manage
int student_id = 12345;
char student_name[50] = "Alice Johnson";
float student_gpa = 3.75;
int student_age = 20;
char student_major[30] = "Electrical Engineering";
// If you have 100 students, you need 500 variables!
User-defined types solve this problem by allowing us to group related data together.
2. Structures (struct)
2.1 What is a Structure?
A structure is a user-defined data type that groups variables of different types under a single name. Think of it as creating your own custom data type.
Python vs C Comparison:
| Python | C |
|---|---|
| Uses classes or dictionaries | Uses struct |
student = {"name": "Alice", "age": 20} |
struct Student student; |
| Dynamic typing | Static typing |
2.2 Declaring a Structure
Basic Syntax:
struct structure_name {
data_type member1;
data_type member2;
// ... more members
};
Example - Student Structure:
struct Student {
int id;
char name[50];
float gpa;
int age;
char major[30];
};
Important Notes:
- Structure declaration ends with a semicolon
; - Members can be of any data type (including other structures)
- The structure declaration itself doesn't allocate memory
2.3 Creating Structure Variables
Method 1: After Structure Declaration
struct Student {
int id;
char name[50];
float gpa;
};
// Create variables
struct Student student1;
struct Student student2, student3;
Method 2: During Structure Declaration
struct Student {
int id;
char name[50];
float gpa;
} student1, student2;
Method 3: Anonymous Structure (less common)
struct {
int id;
char name[50];
float gpa;
} student1, student2;
2.4 Initializing Structure Variables
Method 1: Member-by-Member Assignment
struct Student s1;
s1.id = 12345;
strcpy(s1.name, "Alice Johnson"); // Note: Use strcpy for strings
s1.gpa = 3.75;
Method 2: Initialization at Declaration
struct Student s1 = {12345, "Alice Johnson", 3.75};
Method 3: Designated Initializers (C99 and later)
struct Student s1 = {
.id = 12345,
.name = "Alice Johnson",
.gpa = 3.75
};
Method 4: Partial Initialization
struct Student s1 = {12345}; // Only id is initialized, others are 0/NULL
2.5 Accessing Structure Members
Use the dot operator (.) to access structure members:
struct Student s1;
// Writing to members
s1.id = 12345;
s1.gpa = 3.75;
strcpy(s1.name, "Alice Johnson");
// Reading from members
printf("Student ID: %d\n", s1.id);
printf("Student Name: %s\n", s1.name);
printf("Student GPA: %.2f\n", s1.gpa);
2.6 Nested Structures
Structures can contain other structures as members:
struct Date {
int day;
int month;
int year;
};
struct Student {
int id;
char name[50];
float gpa;
struct Date birthDate; // Nested structure
};
// Usage
struct Student s1;
s1.id = 12345;
s1.birthDate.day = 15;
s1.birthDate.month = 8;
s1.birthDate.year = 2003;
printf("Birth Date: %d/%d/%d\n",
s1.birthDate.day,
s1.birthDate.month,
s1.birthDate.year);
2.7 Array of Structures
You can create arrays of structures to handle multiple records:
struct Student {
int id;
char name[50];
float gpa;
};
// Array of 100 students
struct Student students[100];
// Accessing elements
students[0].id = 12345;
strcpy(students[0].name, "Alice");
students[0].gpa = 3.75;
// Loop through all students
for (int i = 0; i < 100; i++) {
printf("Student %d: %s (GPA: %.2f)\n",
students[i].id,
students[i].name,
students[i].gpa);
}
2.8 Pointers to Structures
You can use pointers with structures:
struct Student s1 = {12345, "Alice", 3.75};
struct Student *ptr = &s1;
// Method 1: Using (*ptr).member
printf("ID: %d\n", (*ptr).id);
// Method 2: Using ptr->member (preferred)
printf("ID: %d\n", ptr->id);
printf("Name: %s\n", ptr->name);
printf("GPA: %.2f\n", ptr->gpa);
The Arrow Operator (->):
ptr->memberis equivalent to(*ptr).member- Much cleaner and more readable
- Commonly used when passing structures to functions
2.9 Structures and Functions
Passing by Value:
void printStudent(struct Student s) {
printf("ID: %d\n", s.id);
printf("Name: %s\n", s.name);
printf("GPA: %.2f\n", s.gpa);
}
// Usage
struct Student s1 = {12345, "Alice", 3.75};
printStudent(s1); // Entire structure is copied
Passing by Reference (Pointer):
void updateGPA(struct Student *s, float newGPA) {
s->gpa = newGPA;
}
// Usage
struct Student s1 = {12345, "Alice", 3.75};
updateGPA(&s1, 3.85); // Pass address of structure
printf("Updated GPA: %.2f\n", s1.gpa); // Output: 3.85
Returning Structures from Functions:
struct Student createStudent(int id, char *name, float gpa) {
struct Student s;
s.id = id;
strcpy(s.name, name);
s.gpa = gpa;
return s;
}
// Usage
struct Student s1 = createStudent(12345, "Alice", 3.75);
2.10 Practical Example: Student Database
#include <stdio.h>
#include <string.h>
struct Student {
int id;
char name[50];
float gpa;
int age;
};
// Function to input student data
void inputStudent(struct Student *s) {
printf("Enter Student ID: ");
scanf("%d", &s->id);
printf("Enter Student Name: ");
scanf(" %[^\n]", s->name);
printf("Enter Student GPA: ");
scanf("%f", &s->gpa);
printf("Enter Student Age: ");
scanf("%d", &s->age);
}
// Function to display student data
void displayStudent(struct Student s) {
printf("\n--- Student Information ---\n");
printf("ID: %d\n", s.id);
printf("Name: %s\n", s.name);
printf("GPA: %.2f\n", s.gpa);
printf("Age: %d\n", s.age);
}
int main() {
struct Student students[3];
// Input data for 3 students
for (int i = 0; i < 3; i++) {
printf("\nEnter details for student %d:\n", i + 1);
inputStudent(&students[i]);
}
// Display all students
printf("\n\n=== All Students ===\n");
for (int i = 0; i < 3; i++) {
displayStudent(students[i]);
}
return 0;
}
3. Enumerations (enum)
3.1 What is an Enumeration?
An enumeration is a user-defined data type consisting of a set of named integer constants. Enums make code more readable by replacing "magic numbers" with meaningful names.
Python vs C Comparison:
| Python | C |
|---|---|
| No built-in enum (uses constants) | Has enum keyword |
RED = 0; GREEN = 1; BLUE = 2 |
enum Color {RED, GREEN, BLUE}; |
3.2 Declaring an Enum
Basic Syntax:
enum enum_name {
constant1,
constant2,
constant3
};
Example:
enum Day {
SUNDAY, // 0
MONDAY, // 1
TUESDAY, // 2
WEDNESDAY, // 3
THURSDAY, // 4
FRIDAY, // 5
SATURDAY // 6
};
Key Points:
- By default, the first constant is assigned value 0
- Each subsequent constant is incremented by 1
- You can explicitly assign values
3.3 Custom Values in Enums
enum Status {
SUCCESS = 1,
FAILURE = 0,
PENDING = -1
};
enum Month {
JANUARY = 1,
FEBRUARY, // 2
MARCH, // 3
APRIL, // 4
MAY, // 5
JUNE, // 6
JULY, // 7
AUGUST, // 8
SEPTEMBER, // 9
OCTOBER, // 10
NOVEMBER, // 11
DECEMBER // 12
};
3.4 Using Enums
#include <stdio.h>
enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
};
int main() {
enum Day today = WEDNESDAY;
printf("Today is day number: %d\n", today); // Output: 3
if (today == WEDNESDAY) {
printf("It's the middle of the week!\n");
}
// Using enum in switch statement
switch (today) {
case MONDAY:
printf("Start of work week\n");
break;
case FRIDAY:
printf("TGIF!\n");
break;
case SATURDAY:
case SUNDAY:
printf("Weekend!\n");
break;
default:
printf("Regular work day\n");
}
return 0;
}
3.5 Enums with Structures
Combining enums with structures creates powerful data models:
enum Grade {
GRADE_A = 90,
GRADE_B = 80,
GRADE_C = 70,
GRADE_D = 60,
GRADE_F = 0
};
enum StudentStatus {
ACTIVE,
GRADUATED,
SUSPENDED,
WITHDRAWN
};
struct Student {
int id;
char name[50];
enum Grade grade;
enum StudentStatus status;
};
int main() {
struct Student s1 = {
.id = 12345,
.name = "Alice",
.grade = GRADE_A,
.status = ACTIVE
};
printf("Student: %s\n", s1.name);
if (s1.status == ACTIVE) {
printf("Status: Active Student\n");
}
if (s1.grade >= GRADE_B) {
printf("Good performance!\n");
}
return 0;
}
3.6 Practical Example: Traffic Light System
#include <stdio.h>
enum TrafficLight {
RED,
YELLOW,
GREEN
};
void displayLightAction(enum TrafficLight light) {
switch (light) {
case RED:
printf("STOP! Red light is on.\n");
break;
case YELLOW:
printf("CAUTION! Yellow light is on.\n");
break;
case GREEN:
printf("GO! Green light is on.\n");
break;
default:
printf("Invalid light state.\n");
}
}
int main() {
enum TrafficLight currentLight = RED;
printf("Traffic Light Simulation:\n\n");
for (int i = 0; i < 3; i++) {
displayLightAction(currentLight);
// Cycle through lights
if (currentLight == RED) {
currentLight = GREEN;
} else if (currentLight == GREEN) {
currentLight = YELLOW;
} else {
currentLight = RED;
}
printf("Waiting...\n\n");
}
return 0;
}
4. Type Definitions (typedef)
4.1 What is typedef?
typedef creates aliases (alternative names) for existing data types. It makes code more readable and easier to maintain.
Basic Syntax:
typedef existing_type new_name;
4.2 typedef with Basic Types
// Create aliases for basic types
typedef int Integer;
typedef float Real;
typedef char Character;
// Usage
Integer age = 25;
Real temperature = 36.5;
Character grade = 'A';
4.3 typedef with Structures
Without typedef:
struct Student {
int id;
char name[50];
float gpa;
};
// Must always use "struct Student"
struct Student s1;
struct Student students[100];
With typedef - Method 1:
struct Student {
int id;
char name[50];
float gpa;
};
typedef struct Student Student;
// Now can use just "Student"
Student s1;
Student students[100];
With typedef - Method 2 (Combined):
typedef struct Student {
int id;
char name[50];
float gpa;
} Student;
// Usage
Student s1;
Student students[100];
With typedef - Method 3 (Anonymous struct):
typedef struct {
int id;
char name[50];
float gpa;
} Student;
// Usage
Student s1;
4.4 typedef with Enums
typedef enum {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
} Day;
// Usage
Day today = WEDNESDAY;
Day weekend[2] = {SATURDAY, SUNDAY};
4.5 typedef with Pointers
typedef int* IntPtr;
typedef struct Student* StudentPtr;
// Usage
IntPtr p1, p2; // Both are int pointers
StudentPtr sptr; // Student pointer
4.6 typedef with Arrays
typedef int IntArray[10];
typedef char String[100];
// Usage
IntArray numbers; // Same as: int numbers[10];
String name; // Same as: char name[100];
4.7 Practical Example: Complex Data Types
#include <stdio.h>
#include <string.h>
// Define enumeration for course grades
typedef enum {
GRADE_A = 4,
GRADE_B = 3,
GRADE_C = 2,
GRADE_D = 1,
GRADE_F = 0
} Grade;
// Define structure for a course
typedef struct {
char code[10];
char name[50];
int credits;
Grade grade;
} Course;
// Define structure for a student
typedef struct {
int id;
char name[50];
Course courses[5];
int numCourses;
float gpa;
} Student;
// Function to calculate GPA
float calculateGPA(Student *s) {
int totalCredits = 0;
float totalPoints = 0.0;
for (int i = 0; i < s->numCourses; i++) {
totalCredits += s->courses[i].credits;
totalPoints += s->courses[i].credits * s->courses[i].grade;
}
if (totalCredits == 0) return 0.0;
return totalPoints / totalCredits;
}
int main() {
Student student = {
.id = 12345,
.name = "Alice Johnson",
.numCourses = 3
};
// Add courses
strcpy(student.courses[0].code, "EE101");
strcpy(student.courses[0].name, "Circuit Analysis");
student.courses[0].credits = 3;
student.courses[0].grade = GRADE_A;
strcpy(student.courses[1].code, "MATH201");
strcpy(student.courses[1].name, "Calculus II");
student.courses[1].credits = 4;
student.courses[1].grade = GRADE_B;
strcpy(student.courses[2].code, "CS101");
strcpy(student.courses[2].name, "Programming");
student.courses[2].credits = 3;
student.courses[2].grade = GRADE_A;
// Calculate and display GPA
student.gpa = calculateGPA(&student);
printf("Student: %s (ID: %d)\n", student.name, student.id);
printf("GPA: %.2f\n\n", student.gpa);
printf("Courses:\n");
for (int i = 0; i < student.numCourses; i++) {
printf(" %s - %s (%d credits): Grade %d\n",
student.courses[i].code,
student.courses[i].name,
student.courses[i].credits,
student.courses[i].grade);
}
return 0;
}
5. File Input/Output
5.1 Why File I/O?
So far, all our programs lose their data when they terminate. File I/O allows programs to:
- Save data permanently
- Read data from external sources
- Create logs and reports
- Share data between programs
Python vs C File Operations:
| Python | C |
|---|---|
f = open("file.txt", "r") |
FILE *f = fopen("file.txt", "r"); |
f.write("text") |
fprintf(f, "text"); |
content = f.read() |
fscanf(f, "%s", buffer); |
f.close() |
fclose(f); |
5.2 File Pointer
In C, files are accessed through file pointers of type FILE*:
FILE *filePointer;
The FILE type is defined in <stdio.h>.
5.3 Opening Files - fopen()
Function Signature:
FILE *fopen(const char *filename, const char *mode);
File Opening Modes:
| Mode | Description | If File Exists | If File Doesn't Exist |
|---|---|---|---|
"r" |
Read only | Opens file | Returns NULL |
"w" |
Write only | Overwrites content | Creates new file |
"a" |
Append | Appends to end | Creates new file |
"r+" |
Read and write | Opens file | Returns NULL |
"w+" |
Read and write | Overwrites content | Creates new file |
"a+" |
Read and append | Opens file | Creates new file |
"rb" |
Read binary | Opens file | Returns NULL |
"wb" |
Write binary | Overwrites content | Creates new file |
"ab" |
Append binary | Appends to end | Creates new file |
Example:
FILE *file;
// Open file for reading
file = fopen("data.txt", "r");
// Always check if file opened successfully
if (file == NULL) {
printf("Error: Could not open file!\n");
return 1;
}
// ... file operations ...
fclose(file);
5.4 Closing Files - fclose()
Always close files after use to:
- Free system resources
- Ensure all data is written to disk
- Prevent data corruption
int fclose(FILE *filePointer);
Returns:
0on successEOFon error
Example:
FILE *file = fopen("data.txt", "r");
if (file != NULL) {
// ... operations ...
fclose(file);
}
5.5 Reading from Text Files
5.5.1 fscanf() - Formatted Input
Similar to scanf(), but reads from a file:
int fscanf(FILE *stream, const char *format, ...);
Example:
FILE *file = fopen("numbers.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
int num;
while (fscanf(file, "%d", &num) == 1) {
printf("Read: %d\n", num);
}
fclose(file);
5.5.2 fgets() - Line Input
Reads a line from a file:
char *fgets(char *str, int n, FILE *stream);
Example:
FILE *file = fopen("text.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
char line[256];
while (fgets(line, sizeof(line), file) != NULL) {
printf("%s", line);
}
fclose(file);
5.5.3 fgetc() - Character Input
Reads a single character:
int fgetc(FILE *stream);
Example:
FILE *file = fopen("text.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
fclose(file);
5.6 Writing to Text Files
5.6.1 fprintf() - Formatted Output
Similar to printf(), but writes to a file:
int fprintf(FILE *stream, const char *format, ...);
Example:
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
fprintf(file, "Student ID: %d\n", 12345);
fprintf(file, "Name: %s\n", "Alice Johnson");
fprintf(file, "GPA: %.2f\n", 3.75);
fclose(file);
5.6.2 fputs() - String Output
Writes a string to a file:
int fputs(const char *str, FILE *stream);
Example:
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
fputs("Hello, World!\n", file);
fputs("This is a test.\n", file);
fclose(file);
5.6.3 fputc() - Character Output
Writes a single character:
int fputc(int char, FILE *stream);
Example:
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
for (char ch = 'A'; ch <= 'Z'; ch++) {
fputc(ch, file);
}
fclose(file);
5.7 File Position Functions
5.7.1 fseek() - Move File Pointer
int fseek(FILE *stream, long offset, int origin);
Origin values:
SEEK_SET- Beginning of fileSEEK_CUR- Current positionSEEK_END- End of file
Example:
FILE *file = fopen("data.txt", "r");
// Move to beginning
fseek(file, 0, SEEK_SET);
// Move 10 bytes from current position
fseek(file, 10, SEEK_CUR);
// Move to end of file
fseek(file, 0, SEEK_END);
5.7.2 ftell() - Get Current Position
long ftell(FILE *stream);
Example:
FILE *file = fopen("data.txt", "r");
long position = ftell(file);
printf("Current position: %ld\n", position);
5.7.3 rewind() - Reset to Beginning
void rewind(FILE *stream);
Example:
FILE *file = fopen("data.txt", "r");
// Read some data...
rewind(file); // Go back to beginning
5.8 Checking End of File - feof()
int feof(FILE *stream);
Returns non-zero if end of file is reached.
Example:
FILE *file = fopen("data.txt", "r");
char ch;
while (!feof(file)) {
ch = fgetc(file);
if (ch != EOF) {
putchar(ch);
}
}
fclose(file);
5.9 Practical Example: Student Records Manager
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float gpa;
int age;
} Student;
// Save student to file
void saveStudent(const char *filename, Student s) {
FILE *file = fopen(filename, "a"); // Append mode
if (file == NULL) {
printf("Error opening file!\n");
return;
}
fprintf(file, "%d,%s,%.2f,%d\n", s.id, s.name, s.gpa, s.age);
fclose(file);
printf("Student record saved successfully!\n");
}
// Load all students from file
void loadStudents(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("No records found!\n");
return;
}
Student s;
printf("\n=== Student Records ===\n");
while (fscanf(file, "%d,%49[^,],%f,%d\n",
&s.id, s.name, &s.gpa, &s.age) == 4) {
printf("ID: %d | Name: %s | GPA: %.2f | Age: %d\n",
s.id, s.name, s.gpa, s.age);
}
fclose(file);
}
// Search for student by ID
int searchStudent(const char *filename, int searchID) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Error opening file!\n");
return 0;
}
Student s;
while (fscanf(file, "%d,%49[^,],%f,%d\n",
&s.id, s.name, &s.gpa, &s.age) == 4) {
if (s.id == searchID) {
printf("\n--- Student Found ---\n");
printf("ID: %d\n", s.id);
printf("Name: %s\n", s.name);
printf("GPA: %.2f\n", s.gpa);
printf("Age: %d\n", s.age);
fclose(file);
return 1;
}
}
fclose(file);
printf("Student not found!\n");
return 0;
}
int main() {
int choice;
Student s;
do {
printf("\n=== Student Management System ===\n");
printf("1. Add Student\n");
printf("2. View All Students\n");
printf("3. Search Student by ID\n");
printf("4. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter Student ID: ");
scanf("%d", &s.id);
printf("Enter Student Name: ");
scanf(" %[^\n]", s.name);
printf("Enter Student GPA: ");
scanf("%f", &s.gpa);
printf("Enter Student Age: ");
scanf("%d", &s.age);
saveStudent("students.txt", s);
break;
case 2:
loadStudents("students.txt");
break;
case 3: {
int searchID;
printf("\nEnter Student ID to search: ");
scanf("%d", &searchID);
searchStudent("students.txt", searchID);
break;
}
case 4:
printf("Exiting program...\n");
break;
default:
printf("Invalid choice!\n");
}
} while (choice != 4);
return 0;
}
5.10 Binary File Operations
Binary files store data in raw binary format, which is more efficient for storing structures.
5.10.1 Writing Binary Data - fwrite()
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
Parameters:
ptr- Pointer to data to writesize- Size of each elementnmemb- Number of elementsstream- File pointer
Example:
typedef struct {
int id;
char name[50];
float gpa;
} Student;
Student s = {12345, "Alice Johnson", 3.75};
FILE *file = fopen("students.dat", "wb");
if (file != NULL) {
fwrite(&s, sizeof(Student), 1, file);
fclose(file);
}
5.10.2 Reading Binary Data - fread()
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Parameters:
ptr- Pointer to memory where data will be storedsize- Size of each elementnmemb- Number of elementsstream- File pointer
Example:
Student s;
FILE *file = fopen("students.dat", "rb");
if (file != NULL) {
while (fread(&s, sizeof(Student), 1, file) == 1) {
printf("ID: %d, Name: %s, GPA: %.2f\n",
s.id, s.name, s.gpa);
}
fclose(file);
}
5.10.3 Binary vs Text Files
| Aspect | Text Files | Binary Files |
|---|---|---|
| Human Readable | Yes | No |
| Size | Larger | Smaller |
| Speed | Slower | Faster |
| Portability | More portable | Less portable |
| Precision | May lose precision | Full precision |
| Best for | Configuration files, logs | Large data, structures |
5.11 Complete Binary File Example
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float gpa;
int age;
} Student;
// Save student to binary file
void saveStudentBinary(const char *filename, Student s) {
FILE *file = fopen(filename, "ab"); // Append binary
if (file == NULL) {
printf("Error opening file!\n");
return;
}
fwrite(&s, sizeof(Student), 1, file);
fclose(file);
printf("Student saved to binary file!\n");
}
// Load all students from binary file
void loadStudentsBinary(const char *filename) {
FILE *file = fopen(filename, "rb"); // Read binary
if (file == NULL) {
printf("No records found!\n");
return;
}
Student s;
printf("\n=== Student Records (Binary) ===\n");
while (fread(&s, sizeof(Student), 1, file) == 1) {
printf("ID: %d | Name: %s | GPA: %.2f | Age: %d\n",
s.id, s.name, s.gpa, s.age);
}
fclose(file);
}
// Count number of records in binary file
int countRecords(const char *filename) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
return 0;
}
// Seek to end of file
fseek(file, 0, SEEK_END);
// Get file size
long fileSize = ftell(file);
fclose(file);
// Calculate number of records
return fileSize / sizeof(Student);
}
// Update student record by ID
int updateStudent(const char *filename, int id, Student newData) {
FILE *file = fopen(filename, "rb+"); // Read and write binary
if (file == NULL) {
printf("Error opening file!\n");
return 0;
}
Student s;
int found = 0;
long position = 0;
// Search for student
while (fread(&s, sizeof(Student), 1, file) == 1) {
if (s.id == id) {
// Move back to the position of this record
fseek(file, position, SEEK_SET);
// Write updated data
fwrite(&newData, sizeof(Student), 1, file);
found = 1;
printf("Student record updated!\n");
break;
}
position = ftell(file);
}
fclose(file);
if (!found) {
printf("Student ID %d not found!\n", id);
}
return found;
}
// Delete student record by ID
int deleteStudent(const char *filename, int id) {
FILE *file = fopen(filename, "rb");
FILE *temp = fopen("temp.dat", "wb");
if (file == NULL || temp == NULL) {
printf("Error opening files!\n");
return 0;
}
Student s;
int found = 0;
// Copy all records except the one to delete
while (fread(&s, sizeof(Student), 1, file) == 1) {
if (s.id == id) {
found = 1;
continue; // Skip this record
}
fwrite(&s, sizeof(Student), 1, temp);
}
fclose(file);
fclose(temp);
// Replace original file with temp file
remove(filename);
rename("temp.dat", filename);
if (found) {
printf("Student record deleted!\n");
} else {
printf("Student ID %d not found!\n", id);
}
return found;
}
int main() {
int choice;
Student s;
do {
printf("\n=== Student Management System (Binary Files) ===\n");
printf("1. Add Student\n");
printf("2. View All Students\n");
printf("3. Count Records\n");
printf("4. Update Student\n");
printf("5. Delete Student\n");
printf("6. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter Student ID: ");
scanf("%d", &s.id);
printf("Enter Student Name: ");
scanf(" %[^\n]", s.name);
printf("Enter Student GPA: ");
scanf("%f", &s.gpa);
printf("Enter Student Age: ");
scanf("%d", &s.age);
saveStudentBinary("students.dat", s);
break;
case 2:
loadStudentsBinary("students.dat");
break;
case 3: {
int count = countRecords("students.dat");
printf("\nTotal records: %d\n", count);
break;
}
case 4: {
int updateID;
printf("\nEnter Student ID to update: ");
scanf("%d", &updateID);
printf("Enter new Student Name: ");
scanf(" %[^\n]", s.name);
printf("Enter new Student GPA: ");
scanf("%f", &s.gpa);
printf("Enter new Student Age: ");
scanf("%d", &s.age);
s.id = updateID;
updateStudent("students.dat", updateID, s);
break;
}
case 5: {
int deleteID;
printf("\nEnter Student ID to delete: ");
scanf("%d", &deleteID);
deleteStudent("students.dat", deleteID);
break;
}
case 6:
printf("Exiting program...\n");
break;
default:
printf("Invalid choice!\n");
}
} while (choice != 6);
return 0;
}