Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

C Structs to Binary Files: A Hands-On Guide for CS 1081 Assignment #12

Learn how to write and read C structs to both text and binary files with this step-by-step tutorial. Perfect for completing Assignment #12 in Computer Science 1081.

C struct to binary file CS 1081 assignment 12 C file I/O tutorial write struct to file in C binary file serialization C student record program C C programming assignment help fwrite fread struct example text vs binary file C validate file integrity C C programming 2026 struct array file operations coding assignment solution guide learn C file handling computer science homework help trending programming skills 2026

Introduction: Why File I/O Matters in 2026

In today's data-driven world, from AI models saving checkpoints to gaming apps storing player profiles, the ability to efficiently write and read structured data to files is a fundamental programming skill. As of May 2026, with the rise of edge computing and real-time data processing, understanding binary file I/O in C gives you a performance edge—binary files are faster and more compact than text files. This tutorial walks you through a typical assignment: storing student records in both text and binary formats, validating data integrity, and mastering struct serialization.

Whether you're building a school management system or a simple leaderboard for a trending mobile game, the concepts here are directly applicable. Let's dive into the code and logic behind Assignment #12.

Step 1: Defining the StudentInfo Struct

First, we need a blueprint for our student data. In C, we use a struct to group related fields. The assignment specifies a char array for name (100 chars), an integer age, a double GPA, and a char grade. No string datatype—just raw char arrays.

#include <stdio.h>
#include <string.h>

#define NAME_LEN 100

struct studentInfo {
    char name[NAME_LEN];
    int age;
    double gpa;
    char grade;
};

This struct is the foundation. Notice we use #define for the name length—good practice for maintainability. Think of it like a character template in a role-playing game (RPG): each student has fixed stats (name, age, GPA, grade) that we can save and load.

Step 2: Initializing an Array of Students

We create an array of 4 students with sample data. In real-world apps, this data might come from a database or user input, but here we hardcode for simplicity.

struct studentInfo students[4] = {
    {"Alice Johnson", 20, 3.75, 'A'},
    {"Bob Smith", 22, 2.90, 'B'},
    {"Carol Davis", 19, 3.50, 'A'},
    {"David Lee", 21, 3.10, 'B'}
};

Each student is like a row in a spreadsheet. We'll later write this data to a text file and then to a binary file.

Step 3: Writing Struct Data to a Text File

Text files are human-readable but slower to parse. The assignment requires a specific format: age + space + gpa + space + grade + space + name + newline. GPA must have 3 digits of precision.

void writeTextFile(struct studentInfo arr[], int size, const char *filename) {
    FILE *fp = fopen(filename, "w");
    if (!fp) { perror("File open failed"); return; }
    for (int i = 0; i < size; i++) {
        fprintf(fp, "%d %.3f %c %s\n", arr[i].age, arr[i].gpa, arr[i].grade, arr[i].name);
    }
    fclose(fp);
}

// Usage:
writeTextFile(students, 4, "studentsOutput.txt");

The %.3f ensures exactly three decimal places for GPA. This is crucial for later comparison when reading back. Think of it as formatting a tweet—you want consistent spacing for easy parsing.

Step 4: Creating a Second Text File with 8 Students

Now we simulate reading external data. Create a file named studentsIn.txt with 8 student records in the same format. You can manually type this or generate it programmatically. Here's an example snippet:

23 3.45 A Emma Wilson
20 2.80 B James Brown
22 3.90 A Sophia Martinez
... (8 total)

This file represents data from another source, like a batch import from a school database. We'll read it into a second array.

Step 5: Reading Text File into an Array and Displaying

Reading structured text requires careful parsing. We use fscanf with the same format but note that %s stops at whitespace, so names must be single tokens (no spaces). The assignment implies names are single words (e.g., "Alice"), but if they contain spaces, you'd need a different approach. For now, assume single-word names.

int readTextFile(struct studentInfo arr[], int maxSize, const char *filename) {
    FILE *fp = fopen(filename, "r");
    if (!fp) { perror("File open failed"); return 0; }
    int count = 0;
    while (count < maxSize && fscanf(fp, "%d %lf %c %99s", &arr[count].age, &arr[count].gpa, &arr[count].grade, arr[count].name) == 4) {
        count++;
    }
    fclose(fp);
    return count;
}

// Display nicely
void displayStudents(struct studentInfo arr[], int size) {
    printf("%-20s %-5s %-8s %-6s\n", "Name", "Age", "GPA", "Grade");
    printf("----------------------------------------\n");
    for (int i = 0; i < size; i++) {
        printf("%-20s %-5d %-8.3f %-6c\n", arr[i].name, arr[i].age, arr[i].gpa, arr[i].grade);
    }
}

The display function formats output as a table—similar to a leaderboard in a gaming app. This makes it easy for users (or graders) to verify data.

Step 6: Writing to a Binary File

Binary files store data in the same format as in memory, making them faster to read/write. The key is to write the entire struct at once using fwrite, not field by field.

void writeBinaryFile(struct studentInfo arr[], int size, const char *filename) {
    FILE *fp = fopen(filename, "wb");
    if (!fp) { perror("File open failed"); return; }
    for (int i = 0; i < size; i++) {
        fwrite(&arr[i], sizeof(struct studentInfo), 1, fp);
    }
    fclose(fp);
}

// Usage after reading studentsIn.txt into secondArray:
writeBinaryFile(secondArray, 8, "studentsOutput.bin");

Notice fwrite takes the address of the struct, size of one struct, count 1, and file pointer. This is like taking a snapshot of the entire object—efficient and exact. In contrast, text writing is like describing the object in words.

Step 7: Reading Binary File and Validating

To verify the binary write, we read it back into a third array and compare field-by-field with the original second array.

int readBinaryFile(struct studentInfo arr[], int maxSize, const char *filename) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) { perror("File open failed"); return 0; }
    int count = 0;
    while (count < maxSize && fread(&arr[count], sizeof(struct studentInfo), 1, fp) == 1) {
        count++;
    }
    fclose(fp);
    return count;
}

int validate(struct studentInfo arr1[], struct studentInfo arr2[], int size) {
    for (int i = 0; i < size; i++) {
        if (strcmp(arr1[i].name, arr2[i].name) != 0) return 0;
        if (arr1[i].age != arr2[i].age) return 0;
        if (arr1[i].gpa != arr2[i].gpa) return 0;
        if (arr1[i].grade != arr2[i].grade) return 0;
    }
    return 1;
}

// In main:
struct studentInfo thirdArray[8];
int n = readBinaryFile(thirdArray, 8, "studentsOutput.bin");
if (n == 8 && validate(secondArray, thirdArray, 8)) {
    printf("Save file was successfully validated\n");
} else {
    printf("Validation failed\n");
}

The validation loop checks every field. This is similar to a checksum in a download—ensuring data integrity after transfer. In 2026, with AI models transferring large binary files, such validation is critical.

Complete Program Structure

Here's how the pieces fit together in main():

int main() {
    // Step 2: Initialize first array
    struct studentInfo students[4] = { ... };
    // Step 3: Write to text file
    writeTextFile(students, 4, "studentsOutput.txt");
    // Step 5: Read from studentsIn.txt into second array
    struct studentInfo secondArray[8];
    int count = readTextFile(secondArray, 8, "studentsIn.txt");
    displayStudents(secondArray, count);
    // Step 6: Write second array to binary
    writeBinaryFile(secondArray, count, "studentsOutput.bin");
    // Step 7: Read binary into third array and validate
    struct studentInfo thirdArray[8];
    int n = readBinaryFile(thirdArray, 8, "studentsOutput.bin");
    if (n == count && validate(secondArray, thirdArray, count)) {
        printf("Save file was successfully validated\n");
    } else {
        printf("Validation failed\n");
    }
    return 0;
}

Common Pitfalls and Tips

  • Binary portability: Binary files are not portable across different systems (endianness, struct padding). For assignment purposes, it's fine, but in real-world apps consider serialization libraries.
  • Name with spaces: The assignment's text format uses space-separated fields, so names must be single words. If you need multi-word names, use a delimiter like comma or fixed-width.
  • GPA precision: In text, use %.3f. In binary, the double is stored exactly, so precision is not an issue.
  • File modes: Always use "wb" and "rb" for binary, "w" and "r" for text. Mixing them can cause errors on some systems (e.g., Windows translates newlines in text mode).

Real-World Connections: Gaming and AI

Binary file I/O is used in game development to save player progress (e.g., a struct with health, inventory, position). In AI, model weights are often saved as binary files for fast loading. The validation step mirrors how a game checks save file integrity to prevent cheating or corruption. As of 2026, with the explosion of AI-generated content, understanding binary serialization helps you build efficient data pipelines.

Conclusion

You've now completed a full cycle: writing structs to text and binary files, reading them back, and validating data. This assignment teaches fundamental file I/O skills that are timeless. Practice by extending the code—add error handling, support for multi-word names, or even a simple search function. Master these concepts, and you'll be ready for more advanced topics like databases or network serialization.

Happy coding, and may your files always be valid!