Files as databases: writing and reading files
Below is a simple C program that uses an array of structs to input details about students and then writes the structures to a file as a database. The program assumes that each student has a name, roll number, and marks.
Certainly! If you want to write each student structure individually in a loop, you can modify the writeToFile
function as follows:
#include <stdio.h>
// Define the structure for a student
struct Student {
char name[50];
int rollNumber;
float marks;
};
// Function to input details of students
void inputStudentDetails(struct Student *students, int numStudents) {
for (int i = 0; i < numStudents; ++i) {
printf("Enter details for student %d:\n", i + 1);
printf("Name: ");
scanf("%s", students[i].name); // Assuming names don't have spaces
printf("Roll Number: ");
scanf("%d", &students[i].rollNumber);
printf("Marks: ");
scanf("%f", &students[i].marks);
}
}
// Function to write student structures to a binary file individually
void writeToFile(struct Student *students, int numStudents, const char *filename) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
perror("Error opening file");
return;
}
for (int i = 0; i < numStudents; ++i) {
fwrite(&students[i], sizeof(struct Student), 1, file);
}
fclose(file);
}
int main() {
int numStudents;
printf("Enter the number of students: ");
scanf("%d", &numStudents);
// Allocate memory for an array of structs
struct Student *students = (struct Student *)malloc(numStudents * sizeof(struct Student));
if (students == NULL) {
perror("Error allocating memory");
return 1;
}
// Input details of students
inputStudentDetails(students, numStudents);
// Write student structures to a binary file individually
writeToFile(students, numStudents, "student_database.bin");
// Free allocated memory
free(students);
printf("Student details written to binary file successfully.\n");
return 0;
}
Let's go through the code step by step to understand its functionality:
#include <stdio.h>
This line includes the standard input/output library, which provides functions like printf
and scanf
.
// Define the structure for a student
struct Student {
char name[50];
int rollNumber;
float marks;
};
This defines a structure named Student
with three members: name
(a character array to store the student's name), rollNumber
(an integer to store the roll number), and marks
(a float to store the student's marks).
// Function to input details of students
void inputStudentDetails(struct Student *students, int numStudents) {
for (int i = 0; i < numStudents; ++i) {
printf("Enter details for student %d:\n", i + 1);
printf("Name: ");
scanf("%s", students[i].name);
printf("Roll Number: ");
scanf("%d", &students[i].rollNumber);
printf("Marks: ");
scanf("%f", &students[i].marks);
}
}
This function, inputStudentDetails
, takes an array of Student
structures (students
) and the number of students (numStudents
). It then uses a loop to input details for each student by prompting the user for the name, roll number, and marks.
// Function to write student structures to a binary file individually
void writeToFile(struct Student *students, int numStudents, const char *filename) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
perror("Error opening file");
return;
}
for (int i = 0; i < numStudents; ++i) {
fwrite(&students[i], sizeof(struct Student), 1, file);
}
fclose(file);
}
This function, writeToFile
, takes an array of Student
structures (students
), the number of students (numStudents
), and a filename as parameters. It opens a file with the specified filename in binary write mode ("wb"
). If the file opening fails, it prints an error message using perror
and returns from the function.
Inside the function, there's a loop that iterates over each student in the array and uses fwrite
to write the student structure to the file. The third argument of fwrite
is set to 1
because we are writing one structure at a time. The size of each structure is calculated using sizeof(struct Student)
.
int main() {
int numStudents;
printf("Enter the number of students: ");
scanf("%d", &numStudents);
// Allocate memory for an array of structs
struct Student *students = (struct Student *)malloc(numStudents * sizeof(struct Student));
if (students == NULL) {
perror("Error allocating memory");
return 1;
}
// Input details of students
inputStudentDetails(students, numStudents);
// Write student structures to a binary file individually
writeToFile(students, numStudents, "student_database.bin");
// Free allocated memory
free(students);
printf("Student details written to binary file successfully.\n");
return 0;
}
In the main
function, the program begins by prompting the user to enter the number of students. It then dynamically allocates memory for an array of Student
structures using malloc
. If the memory allocation fails, it prints an error message and exits the program with a return value of 1
.
The inputStudentDetails
function is then called to gather details for each student from the user.
Finally, the writeToFile
function is called to write each student structure to a binary file named "student_database.bin." After writing the data, the dynamically allocated memory is freed using free
.
The program concludes by printing a success message and returning 0
from the main
function, indicating successful execution.
Here's a program that opens the binary file created by the previous program, reads all structures into an array, takes a roll number from the user, finds the student from the array, and outputs details of that student to the console. It continues to take roll numbers until the user types "done":
#include <stdio.h>
// Define the structure for a student
struct Student {
char name[50];
int rollNumber;
float marks;
};
// Function to read student structures from a binary file individually
void readFromFile(struct Student *students, int numStudents, const char *filename) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
perror("Error opening file");
return;
}
for (int i = 0; i < numStudents; ++i) {
fread(&students[i], sizeof(struct Student), 1, file);
}
fclose(file);
}
// Function to find and display details of a student by roll number
void findAndDisplayStudent(struct Student *students, int numStudents, int rollNumber) {
for (int i = 0; i < numStudents; ++i) {
if (students[i].rollNumber == rollNumber) {
printf("Student found!\n");
printf("Name: %s\n", students[i].name);
printf("Roll Number: %d\n", students[i].rollNumber);
printf("Marks: %.2f\n", students[i].marks);
return; // Student found, exit the function
}
}
// If loop completes, the student was not found
printf("Student with Roll Number %d not found.\n", rollNumber);
}
int main() {
int numStudents;
printf("Enter the number of students: ");
scanf("%d", &numStudents);
// Allocate memory for an array of structs
struct Student *students = (struct Student *)malloc(numStudents * sizeof(struct Student));
if (students == NULL) {
perror("Error allocating memory");
return 1;
}
// Read student structures from the binary file individually
readFromFile(students, numStudents, "student_database.bin");
// Take roll numbers until the user types "done"
while (1) {
int rollNumber;
printf("Enter a roll number (type 'done' to exit): ");
if (scanf("%d", &rollNumber) != 1) {
// Handle invalid input
printf("Invalid input. Exiting.\n");
break;
}
if (rollNumber == -1) {
// Exit the loop if the user types -1
break;
}
// Find and display details of the student
findAndDisplayStudent(students, numStudents, rollNumber);
}
// Free allocated memory
free(students);
return 0;
}
Let's break down the program step by step:
#include <stdio.h>
This line includes the standard input/output library, which provides functions like printf
and scanf
.
// Define the structure for a student
struct Student {
char name[50];
int rollNumber;
float marks;
};
This defines a structure named Student
with three members: name
(a character array to store the student's name), rollNumber
(an integer to store the roll number), and marks
(a float to store the student's marks).
// Function to read student structures from a binary file individually
void readFromFile(struct Student *students, int numStudents, const char *filename) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
perror("Error opening file");
return;
}
for (int i = 0; i < numStudents; ++i) {
fread(&students[i], sizeof(struct Student), 1, file);
}
fclose(file);
}
This function, readFromFile
, takes an array of Student
structures (students
), the number of students (numStudents
), and a filename as parameters. It opens a binary file with the specified filename in read mode ("rb"
). If the file opening fails, it prints an error message using perror
and returns from the function.
Inside the function, there's a loop that iterates over each student in the array. It uses fread
to read the student structure from the file into the array. The third argument of fread
is set to 1
because we are reading one structure at a time. The size of each structure is calculated using sizeof(struct Student)
.
// Function to find and display details of a student by roll number
void findAndDisplayStudent(struct Student *students, int numStudents, int rollNumber) {
for (int i = 0; i < numStudents; ++i) {
if (students[i].rollNumber == rollNumber) {
printf("Student found!\n");
printf("Name: %s\n", students[i].name);
printf("Roll Number: %d\n", students[i].rollNumber);
printf("Marks: %.2f\n", students[i].marks);
return; // Student found, exit the function
}
}
// If loop completes, the student was not found
printf("Student with Roll Number %d not found.\n", rollNumber);
}
This function, findAndDisplayStudent
, takes an array of Student
structures (students
), the number of students (numStudents
), and a roll number as parameters. It searches for a student with the given roll number in the array and displays their details if found.
int main() {
int numStudents;
printf("Enter the number of students: ");
scanf("%d", &numStudents);
// Allocate memory for an array of structs
struct Student *students = (struct Student *)malloc(numStudents * sizeof(struct Student));
if (students == NULL) {
perror("Error allocating memory");
return 1;
}
// Read student structures from the binary file individually
readFromFile(students, numStudents, "student_database.bin");
// Take roll numbers until the user types "done"
while (1) {
int rollNumber;
printf("Enter a roll number (type 'done' to exit): ");
if (scanf("%d", &rollNumber) != 1) {
// Handle invalid input
printf("Invalid input. Exiting.\n");
break;
}
if (rollNumber == -1) {
// Exit the loop if the user types -1
break;
}
// Find and display details of the student
findAndDisplayStudent(students, numStudents, rollNumber);
}
// Free allocated memory
free(students);
return 0;
}
In the main
function, the program starts by prompting the user to enter the number of students. It then dynamically allocates memory for an array of Student
structures using malloc
. If the memory allocation fails, it prints an error message and exits the program with a return value of 1
.
The readFromFile
function is then called to read each student structure individually from the binary file into the array.
The program enters a loop where it continuously takes roll numbers from the user until the user types "done" or enters -1. It uses scanf
to read integer input, and if the input is not an integer, it prints an error message and exits the loop. If the user types -1, the loop also exits.
For each valid roll number, the findAndDisplayStudent
function is called to search for and display details of the corresponding student.
The loop continues until the user types "done" or -1.
Finally, the dynamically allocated memory is freed using free
. The program concludes by returning 0 from the main
function, indicating successful execution.