c

examples

examples.c🔧
/*
 * =============================================================================
 *                         BINARY FILES IN C
 *                         Code Examples
 * =============================================================================
 * 
 * This file demonstrates various techniques for working with binary files.
 * Each example is self-contained and illustrates different concepts.
 * 
 * Compilation: gcc examples.c -o examples
 * =============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>

/*
 * =============================================================================
 * EXAMPLE 1: Basic Binary Write and Read
 * =============================================================================
 * Demonstrates fundamental fwrite() and fread() operations.
 */
void example_basic_binary_io(void) {
    printf("=== Example 1: Basic Binary Write and Read ===\n\n");
    
    // Writing binary data
    FILE *fp = fopen("basic.bin", "wb");
    if (fp == NULL) {
        perror("Error opening file for writing");
        return;
    }
    
    int numbers[] = {10, 20, 30, 40, 50};
    int count = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("Writing %d integers in binary format...\n", count);
    size_t written = fwrite(numbers, sizeof(int), count, fp);
    printf("Wrote %zu elements (%zu bytes)\n", written, written * sizeof(int));
    
    fclose(fp);
    
    // Reading binary data
    fp = fopen("basic.bin", "rb");
    if (fp == NULL) {
        perror("Error opening file for reading");
        return;
    }
    
    int read_numbers[5];
    size_t read_count = fread(read_numbers, sizeof(int), 5, fp);
    
    printf("\nRead %zu integers:\n", read_count);
    for (size_t i = 0; i < read_count; i++) {
        printf("  [%zu] = %d\n", i, read_numbers[i]);
    }
    
    fclose(fp);
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 2: Writing Different Data Types
 * =============================================================================
 * Shows how to write various primitive types to a binary file.
 */
void example_multiple_types(void) {
    printf("=== Example 2: Writing Different Data Types ===\n\n");
    
    FILE *fp = fopen("types.bin", "wb");
    if (fp == NULL) return;
    
    // Write different types
    char c = 'A';
    short s = 1234;
    int i = 123456;
    long l = 1234567890L;
    float f = 3.14159f;
    double d = 2.718281828;
    
    fwrite(&c, sizeof(char), 1, fp);
    fwrite(&s, sizeof(short), 1, fp);
    fwrite(&i, sizeof(int), 1, fp);
    fwrite(&l, sizeof(long), 1, fp);
    fwrite(&f, sizeof(float), 1, fp);
    fwrite(&d, sizeof(double), 1, fp);
    
    printf("Wrote the following to types.bin:\n");
    printf("  char:   '%c' (%zu bytes)\n", c, sizeof(char));
    printf("  short:  %d (%zu bytes)\n", s, sizeof(short));
    printf("  int:    %d (%zu bytes)\n", i, sizeof(int));
    printf("  long:   %ld (%zu bytes)\n", l, sizeof(long));
    printf("  float:  %f (%zu bytes)\n", f, sizeof(float));
    printf("  double: %f (%zu bytes)\n", d, sizeof(double));
    
    long total = sizeof(char) + sizeof(short) + sizeof(int) + 
                 sizeof(long) + sizeof(float) + sizeof(double);
    printf("\nTotal bytes written: %ld\n", total);
    
    fclose(fp);
    
    // Read back and verify
    printf("\nReading back...\n");
    fp = fopen("types.bin", "rb");
    if (fp != NULL) {
        char rc; short rs; int ri; long rl; float rf; double rd;
        
        fread(&rc, sizeof(char), 1, fp);
        fread(&rs, sizeof(short), 1, fp);
        fread(&ri, sizeof(int), 1, fp);
        fread(&rl, sizeof(long), 1, fp);
        fread(&rf, sizeof(float), 1, fp);
        fread(&rd, sizeof(double), 1, fp);
        
        printf("  char:   '%c'\n", rc);
        printf("  short:  %d\n", rs);
        printf("  int:    %d\n", ri);
        printf("  long:   %ld\n", rl);
        printf("  float:  %f\n", rf);
        printf("  double: %f\n", rd);
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 3: Structure Serialization
 * =============================================================================
 * Demonstrates writing and reading entire structures.
 */
void example_structure_serialization(void) {
    printf("=== Example 3: Structure Serialization ===\n\n");
    
    struct Employee {
        int id;
        char name[50];
        char department[30];
        float salary;
        int years_employed;
    };
    
    // Create employee records
    struct Employee employees[] = {
        {1001, "Alice Johnson", "Engineering", 75000.00, 5},
        {1002, "Bob Smith", "Marketing", 65000.00, 3},
        {1003, "Carol Williams", "Finance", 72000.00, 7},
        {1004, "David Brown", "Engineering", 80000.00, 10},
        {1005, "Eva Martinez", "HR", 58000.00, 2}
    };
    int emp_count = sizeof(employees) / sizeof(employees[0]);
    
    printf("Structure size: %zu bytes\n", sizeof(struct Employee));
    
    // Write to binary file
    FILE *fp = fopen("employees.bin", "wb");
    if (fp == NULL) return;
    
    // Write count first
    fwrite(&emp_count, sizeof(int), 1, fp);
    
    // Write all records
    size_t written = fwrite(employees, sizeof(struct Employee), emp_count, fp);
    
    printf("Wrote %zu employee records\n", written);
    printf("Total file size: %zu bytes\n", 
           sizeof(int) + written * sizeof(struct Employee));
    
    fclose(fp);
    
    // Read back
    printf("\nReading back employee records:\n");
    printf("%-6s %-20s %-15s %10s %5s\n", 
           "ID", "Name", "Department", "Salary", "Years");
    printf("%-6s %-20s %-15s %10s %5s\n", 
           "----", "----", "----------", "------", "-----");
    
    fp = fopen("employees.bin", "rb");
    if (fp != NULL) {
        int count;
        fread(&count, sizeof(int), 1, fp);
        
        struct Employee e;
        for (int i = 0; i < count; i++) {
            fread(&e, sizeof(struct Employee), 1, fp);
            printf("%-6d %-20s %-15s $%9.2f %5d\n",
                   e.id, e.name, e.department, e.salary, e.years_employed);
        }
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 4: Binary File with Header
 * =============================================================================
 * Shows how to create a binary file format with a header.
 */
#define MAGIC_NUMBER 0x44415441  // "DATA" in hex

struct FileHeader {
    uint32_t magic;           // Magic number to identify file type
    uint32_t version;         // File format version
    uint32_t record_count;    // Number of data records
    uint32_t record_size;     // Size of each record
    time_t   created;         // Creation timestamp
    char     creator[32];     // Creator name
};

struct DataRecord {
    int32_t id;
    char    label[20];
    double  value;
};

void example_file_with_header(void) {
    printf("=== Example 4: Binary File with Header ===\n\n");
    
    // Prepare header
    struct FileHeader header;
    header.magic = MAGIC_NUMBER;
    header.version = 1;
    header.record_count = 5;
    header.record_size = sizeof(struct DataRecord);
    header.created = time(NULL);
    strncpy(header.creator, "Example Program", sizeof(header.creator) - 1);
    
    // Prepare data
    struct DataRecord records[] = {
        {1, "Alpha", 1.1},
        {2, "Beta", 2.2},
        {3, "Gamma", 3.3},
        {4, "Delta", 4.4},
        {5, "Epsilon", 5.5}
    };
    
    // Write file
    FILE *fp = fopen("data_with_header.bin", "wb");
    if (fp == NULL) return;
    
    fwrite(&header, sizeof(struct FileHeader), 1, fp);
    fwrite(records, sizeof(struct DataRecord), header.record_count, fp);
    
    printf("Created file with:\n");
    printf("  Header size: %zu bytes\n", sizeof(struct FileHeader));
    printf("  Record size: %zu bytes\n", sizeof(struct DataRecord));
    printf("  Record count: %u\n", header.record_count);
    printf("  Total size: %zu bytes\n", 
           sizeof(struct FileHeader) + header.record_count * sizeof(struct DataRecord));
    
    fclose(fp);
    
    // Read and validate file
    printf("\nReading and validating file:\n");
    
    fp = fopen("data_with_header.bin", "rb");
    if (fp != NULL) {
        struct FileHeader read_header;
        fread(&read_header, sizeof(struct FileHeader), 1, fp);
        
        // Validate magic number
        if (read_header.magic != MAGIC_NUMBER) {
            printf("ERROR: Invalid file format (bad magic number)\n");
            fclose(fp);
            return;
        }
        
        printf("  Magic: 0x%08X (valid)\n", read_header.magic);
        printf("  Version: %u\n", read_header.version);
        printf("  Records: %u\n", read_header.record_count);
        printf("  Created: %s", ctime(&read_header.created));
        printf("  Creator: %s\n", read_header.creator);
        
        printf("\nData records:\n");
        struct DataRecord rec;
        for (uint32_t i = 0; i < read_header.record_count; i++) {
            fread(&rec, sizeof(struct DataRecord), 1, fp);
            printf("  ID %d: %s = %.2f\n", rec.id, rec.label, rec.value);
        }
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 5: Array Storage and Retrieval
 * =============================================================================
 * Demonstrates efficient storage of large arrays.
 */
void example_array_storage(void) {
    printf("=== Example 5: Array Storage and Retrieval ===\n\n");
    
    #define ARRAY_SIZE 1000
    
    // Create large array of doubles
    double *data = malloc(ARRAY_SIZE * sizeof(double));
    if (data == NULL) return;
    
    printf("Generating %d random values...\n", ARRAY_SIZE);
    srand(time(NULL));
    for (int i = 0; i < ARRAY_SIZE; i++) {
        data[i] = (double)rand() / RAND_MAX * 100.0;
    }
    
    // Write to binary file
    FILE *fp = fopen("array.bin", "wb");
    if (fp != NULL) {
        // Write size first
        int size = ARRAY_SIZE;
        fwrite(&size, sizeof(int), 1, fp);
        
        // Write entire array at once
        size_t written = fwrite(data, sizeof(double), ARRAY_SIZE, fp);
        
        printf("Wrote %zu doubles (%zu bytes)\n", written, written * sizeof(double));
        fclose(fp);
    }
    
    // Read back
    printf("\nReading back...\n");
    
    double *read_data = NULL;
    fp = fopen("array.bin", "rb");
    if (fp != NULL) {
        int size;
        fread(&size, sizeof(int), 1, fp);
        
        read_data = malloc(size * sizeof(double));
        if (read_data != NULL) {
            size_t read_count = fread(read_data, sizeof(double), size, fp);
            printf("Read %zu doubles\n", read_count);
            
            // Verify first and last few
            printf("\nFirst 5 values:\n");
            for (int i = 0; i < 5; i++) {
                printf("  [%d] Original: %.4f, Read: %.4f %s\n", 
                       i, data[i], read_data[i],
                       data[i] == read_data[i] ? "✓" : "✗");
            }
            
            printf("\nLast 5 values:\n");
            for (int i = ARRAY_SIZE - 5; i < ARRAY_SIZE; i++) {
                printf("  [%d] Original: %.4f, Read: %.4f %s\n",
                       i, data[i], read_data[i],
                       data[i] == read_data[i] ? "✓" : "✗");
            }
            
            free(read_data);
        }
        fclose(fp);
    }
    
    free(data);
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 6: Fixed-Width Integer Types
 * =============================================================================
 * Using stdint.h types for portable binary files.
 */
void example_fixed_width_types(void) {
    printf("=== Example 6: Fixed-Width Integer Types ===\n\n");
    
    struct PortableRecord {
        int8_t   tiny;     // Always 1 byte
        int16_t  small;    // Always 2 bytes
        int32_t  medium;   // Always 4 bytes
        int64_t  large;    // Always 8 bytes
        uint32_t unsigned_val;
    };
    
    printf("Sizes of fixed-width types:\n");
    printf("  int8_t:   %zu bytes\n", sizeof(int8_t));
    printf("  int16_t:  %zu bytes\n", sizeof(int16_t));
    printf("  int32_t:  %zu bytes\n", sizeof(int32_t));
    printf("  int64_t:  %zu bytes\n", sizeof(int64_t));
    printf("  uint32_t: %zu bytes\n", sizeof(uint32_t));
    printf("\nTotal struct size: %zu bytes\n", sizeof(struct PortableRecord));
    
    struct PortableRecord rec = {
        .tiny = 127,
        .small = 32000,
        .medium = 2000000000,
        .large = 9000000000000000000LL,
        .unsigned_val = 4000000000U
    };
    
    // Write
    FILE *fp = fopen("portable.bin", "wb");
    if (fp != NULL) {
        fwrite(&rec, sizeof(struct PortableRecord), 1, fp);
        fclose(fp);
        printf("\nWrote record to portable.bin\n");
    }
    
    // Read back
    fp = fopen("portable.bin", "rb");
    if (fp != NULL) {
        struct PortableRecord read_rec;
        fread(&read_rec, sizeof(struct PortableRecord), 1, fp);
        
        printf("\nRead back values:\n");
        printf("  tiny:    %d\n", read_rec.tiny);
        printf("  small:   %d\n", read_rec.small);
        printf("  medium:  %d\n", read_rec.medium);
        printf("  large:   %ld\n", read_rec.large);
        printf("  unsigned: %u\n", read_rec.unsigned_val);
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 7: Detecting Endianness
 * =============================================================================
 * Shows how to detect and handle byte order.
 */
void example_endianness(void) {
    printf("=== Example 7: Detecting Endianness ===\n\n");
    
    // Detect system endianness
    union {
        uint32_t value;
        uint8_t bytes[4];
    } test;
    
    test.value = 0x01020304;
    
    printf("Test value: 0x01020304\n");
    printf("Byte layout in memory: %02X %02X %02X %02X\n",
           test.bytes[0], test.bytes[1], test.bytes[2], test.bytes[3]);
    
    if (test.bytes[0] == 0x04) {
        printf("System is LITTLE-ENDIAN\n");
    } else {
        printf("System is BIG-ENDIAN\n");
    }
    
    // Byte swapping functions
    printf("\nByte swapping demonstration:\n");
    
    uint16_t val16 = 0x1234;
    uint32_t val32 = 0x12345678;
    
    // Swap 16-bit
    uint16_t swapped16 = (val16 << 8) | (val16 >> 8);
    printf("  16-bit: 0x%04X -> 0x%04X\n", val16, swapped16);
    
    // Swap 32-bit
    uint32_t swapped32 = ((val32 << 24) & 0xFF000000) |
                         ((val32 << 8)  & 0x00FF0000) |
                         ((val32 >> 8)  & 0x0000FF00) |
                         ((val32 >> 24) & 0x000000FF);
    printf("  32-bit: 0x%08X -> 0x%08X\n", val32, swapped32);
    
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 8: Binary vs Text Size Comparison
 * =============================================================================
 * Compares file sizes between text and binary storage.
 */
void example_size_comparison(void) {
    printf("=== Example 8: Binary vs Text Size Comparison ===\n\n");
    
    #define NUM_VALUES 100
    double values[NUM_VALUES];
    
    // Generate values
    for (int i = 0; i < NUM_VALUES; i++) {
        values[i] = (double)i * 3.14159265358979;
    }
    
    // Write as text
    FILE *fp_text = fopen("values.txt", "w");
    if (fp_text != NULL) {
        for (int i = 0; i < NUM_VALUES; i++) {
            fprintf(fp_text, "%.15f\n", values[i]);
        }
        fclose(fp_text);
    }
    
    // Write as binary
    FILE *fp_bin = fopen("values.bin", "wb");
    if (fp_bin != NULL) {
        fwrite(values, sizeof(double), NUM_VALUES, fp_bin);
        fclose(fp_bin);
    }
    
    // Compare sizes
    fp_text = fopen("values.txt", "rb");
    fp_bin = fopen("values.bin", "rb");
    
    if (fp_text != NULL && fp_bin != NULL) {
        fseek(fp_text, 0, SEEK_END);
        fseek(fp_bin, 0, SEEK_END);
        
        long text_size = ftell(fp_text);
        long bin_size = ftell(fp_bin);
        
        printf("Storing %d double values:\n\n", NUM_VALUES);
        printf("Text file size:   %ld bytes\n", text_size);
        printf("Binary file size: %ld bytes\n", bin_size);
        printf("\nBinary is %.1f%% smaller\n", 
               100.0 * (text_size - bin_size) / text_size);
        printf("Binary is %.1fx smaller\n", (double)text_size / bin_size);
        
        fclose(fp_text);
        fclose(fp_bin);
    }
    
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 9: Reading Until EOF
 * =============================================================================
 * Demonstrates reading binary file of unknown size.
 */
void example_read_until_eof(void) {
    printf("=== Example 9: Reading Until EOF ===\n\n");
    
    // Create test file with unknown number of records
    FILE *fp = fopen("unknown_count.bin", "wb");
    if (fp != NULL) {
        int values[] = {10, 20, 30, 40, 50, 60, 70};
        fwrite(values, sizeof(int), 7, fp);
        fclose(fp);
        printf("Created file with 7 integers\n\n");
    }
    
    // Read without knowing count in advance
    fp = fopen("unknown_count.bin", "rb");
    if (fp != NULL) {
        int value;
        int count = 0;
        
        printf("Reading values until EOF:\n");
        
        while (fread(&value, sizeof(int), 1, fp) == 1) {
            printf("  Value %d: %d\n", count, value);
            count++;
        }
        
        if (feof(fp)) {
            printf("\nReached end of file\n");
        } else if (ferror(fp)) {
            printf("\nRead error occurred\n");
        }
        
        printf("Total values read: %d\n", count);
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 10: Image-like Data (2D Array)
 * =============================================================================
 * Storing and retrieving 2D array data.
 */
void example_2d_array(void) {
    printf("=== Example 10: 2D Array (Image-like Data) ===\n\n");
    
    #define WIDTH 10
    #define HEIGHT 8
    
    // Create 2D array (grayscale image simulation)
    unsigned char image[HEIGHT][WIDTH];
    
    printf("Creating %dx%d image...\n", WIDTH, HEIGHT);
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            // Create gradient pattern
            image[y][x] = (unsigned char)((y * WIDTH + x) * 3);
        }
    }
    
    // Write image data
    FILE *fp = fopen("image.bin", "wb");
    if (fp != NULL) {
        // Write dimensions first
        int dims[2] = {WIDTH, HEIGHT};
        fwrite(dims, sizeof(int), 2, fp);
        
        // Write pixel data
        fwrite(image, sizeof(unsigned char), WIDTH * HEIGHT, fp);
        
        printf("Wrote image (%zu bytes)\n", 
               2 * sizeof(int) + WIDTH * HEIGHT * sizeof(unsigned char));
        fclose(fp);
    }
    
    // Read back
    printf("\nReading back image:\n\n");
    
    fp = fopen("image.bin", "rb");
    if (fp != NULL) {
        int dims[2];
        fread(dims, sizeof(int), 2, fp);
        printf("Image dimensions: %dx%d\n\n", dims[0], dims[1]);
        
        unsigned char read_image[HEIGHT][WIDTH];
        fread(read_image, sizeof(unsigned char), WIDTH * HEIGHT, fp);
        
        // Display as ASCII art
        printf("Pixel values (first 5x5):\n");
        for (int y = 0; y < 5; y++) {
            for (int x = 0; x < 5; x++) {
                printf("%3d ", read_image[y][x]);
            }
            printf("\n");
        }
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 11: Chunked File Format
 * =============================================================================
 * Demonstrates a chunked/tagged file format.
 */
void example_chunked_format(void) {
    printf("=== Example 11: Chunked File Format ===\n\n");
    
    struct ChunkHeader {
        char type[4];      // 4-character chunk type
        uint32_t size;     // Size of chunk data
    };
    
    FILE *fp = fopen("chunked.bin", "wb");
    if (fp == NULL) return;
    
    // Write VERS chunk (version info)
    struct ChunkHeader vers_header = {{'V','E','R','S'}, sizeof(uint32_t)};
    uint32_t version = 1;
    fwrite(&vers_header, sizeof(struct ChunkHeader), 1, fp);
    fwrite(&version, sizeof(uint32_t), 1, fp);
    printf("Wrote VERS chunk: version %u\n", version);
    
    // Write NAME chunk
    const char *name = "Example Chunked File";
    struct ChunkHeader name_header = {{'N','A','M','E'}, strlen(name) + 1};
    fwrite(&name_header, sizeof(struct ChunkHeader), 1, fp);
    fwrite(name, 1, strlen(name) + 1, fp);
    printf("Wrote NAME chunk: %s\n", name);
    
    // Write DATA chunk
    int data[] = {100, 200, 300, 400, 500};
    struct ChunkHeader data_header = {{'D','A','T','A'}, sizeof(data)};
    fwrite(&data_header, sizeof(struct ChunkHeader), 1, fp);
    fwrite(data, sizeof(int), 5, fp);
    printf("Wrote DATA chunk: 5 integers\n");
    
    fclose(fp);
    
    // Read back chunks
    printf("\nReading chunks:\n\n");
    
    fp = fopen("chunked.bin", "rb");
    if (fp != NULL) {
        struct ChunkHeader header;
        
        while (fread(&header, sizeof(struct ChunkHeader), 1, fp) == 1) {
            printf("Chunk: %.4s, Size: %u bytes\n", header.type, header.size);
            
            // Handle known chunk types
            if (memcmp(header.type, "VERS", 4) == 0) {
                uint32_t v;
                fread(&v, sizeof(uint32_t), 1, fp);
                printf("  Version: %u\n", v);
            }
            else if (memcmp(header.type, "NAME", 4) == 0) {
                char *n = malloc(header.size);
                fread(n, 1, header.size, fp);
                printf("  Name: %s\n", n);
                free(n);
            }
            else if (memcmp(header.type, "DATA", 4) == 0) {
                int count = header.size / sizeof(int);
                int *d = malloc(header.size);
                fread(d, sizeof(int), count, fp);
                printf("  Data: ");
                for (int i = 0; i < count; i++) {
                    printf("%d ", d[i]);
                }
                printf("\n");
                free(d);
            }
            else {
                // Skip unknown chunks
                fseek(fp, header.size, SEEK_CUR);
                printf("  (skipped unknown chunk)\n");
            }
        }
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 12: Database-style Binary File
 * =============================================================================
 * A complete example of a simple binary database.
 */
#define DB_MAGIC 0x53494D44  // "SIMD" - Simple DB
#define DB_VERSION 1

struct DBHeader_Ex {
    uint32_t magic;
    uint32_t version;
    uint32_t record_count;
    uint32_t next_id;
};

struct DBRecord {
    uint32_t id;
    char name[32];
    double value;
    uint8_t active;
    uint8_t padding[3];  // Explicit padding
};

void example_database(void) {
    printf("=== Example 12: Database-style Binary File ===\n\n");
    
    const char *db_file = "database.bin";
    
    // Create database with initial records
    printf("Creating database...\n");
    
    FILE *fp = fopen(db_file, "wb");
    if (fp == NULL) return;
    
    struct DBHeader_Ex header = {
        .magic = DB_MAGIC,
        .version = DB_VERSION,
        .record_count = 0,
        .next_id = 1
    };
    
    struct DBRecord records[] = {
        {1, "Item One", 10.50, 1, {0}},
        {2, "Item Two", 25.00, 1, {0}},
        {3, "Item Three", 7.99, 0, {0}},
        {4, "Item Four", 150.00, 1, {0}}
    };
    header.record_count = 4;
    header.next_id = 5;
    
    fwrite(&header, sizeof(struct DBHeader_Ex), 1, fp);
    fwrite(records, sizeof(struct DBRecord), 4, fp);
    fclose(fp);
    
    printf("Created database with %u records\n\n", header.record_count);
    
    // Read and display database
    printf("Reading database:\n");
    
    fp = fopen(db_file, "rb");
    if (fp != NULL) {
        struct DBHeader_Ex h;
        fread(&h, sizeof(struct DBHeader_Ex), 1, fp);
        
        if (h.magic != DB_MAGIC) {
            printf("Invalid database file!\n");
            fclose(fp);
            return;
        }
        
        printf("Database v%u: %u records\n\n", h.version, h.record_count);
        
        printf("%-4s %-20s %10s %6s\n", "ID", "Name", "Value", "Active");
        printf("%-4s %-20s %10s %6s\n", "--", "----", "-----", "------");
        
        struct DBRecord r;
        for (uint32_t i = 0; i < h.record_count; i++) {
            fread(&r, sizeof(struct DBRecord), 1, fp);
            printf("%-4u %-20s %10.2f %6s\n",
                   r.id, r.name, r.value, r.active ? "Yes" : "No");
        }
        
        fclose(fp);
    }
    printf("\n");
}

/*
 * =============================================================================
 * EXAMPLE 13: Error Handling Best Practices
 * =============================================================================
 * Comprehensive error checking for binary I/O.
 */
void example_error_handling(void) {
    printf("=== Example 13: Error Handling Best Practices ===\n\n");
    
    const char *filename = "error_test.bin";
    int data[] = {1, 2, 3, 4, 5};
    int count = 5;
    int result = 0;  // 0 = success, -1 = error
    
    // Write with full error checking
    printf("Writing with full error checking...\n");
    
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) {
        perror("  Failed to open file");
        return;
    }
    
    size_t written = fwrite(data, sizeof(int), count, fp);
    if (written != count) {
        if (ferror(fp)) {
            perror("  Write error");
            result = -1;
        }
    }
    
    // Check fflush
    if (fflush(fp) != 0) {
        perror("  Flush error");
        result = -1;
    }
    
    // Check fclose
    if (fclose(fp) != 0) {
        perror("  Close error");
        result = -1;
    }
    
    if (result == 0) {
        printf("  Write successful: %zu elements\n", written);
    }
    
    // Read with full error checking
    printf("\nReading with full error checking...\n");
    
    int read_data[10];
    result = 0;
    
    fp = fopen(filename, "rb");
    if (fp == NULL) {
        perror("  Failed to open file");
        return;
    }
    
    size_t read_count = fread(read_data, sizeof(int), count, fp);
    
    if (read_count != count) {
        if (feof(fp)) {
            printf("  Warning: Only read %zu of %d elements (EOF)\n", 
                   read_count, count);
        }
        if (ferror(fp)) {
            perror("  Read error");
            result = -1;
        }
    } else {
        printf("  Read successful: %zu elements\n", read_count);
    }
    
    // Verify data
    printf("\nVerifying data integrity:\n");
    int match = 1;
    for (size_t i = 0; i < read_count; i++) {
        if (data[i] != read_data[i]) {
            printf("  Mismatch at index %zu: wrote %d, read %d\n",
                   i, data[i], read_data[i]);
            match = 0;
        }
    }
    if (match) {
        printf("  All values match!\n");
    }
    
    fclose(fp);
    printf("\n");
}

/*
 * =============================================================================
 * MAIN FUNCTION - Run All Examples
 * =============================================================================
 */
int main(void) {
    printf("\n");
    printf("╔═══════════════════════════════════════════════════════════════╗\n");
    printf("║              BINARY FILES IN C - CODE EXAMPLES                ║\n");
    printf("╚═══════════════════════════════════════════════════════════════╝\n\n");
    
    example_basic_binary_io();
    example_multiple_types();
    example_structure_serialization();
    example_file_with_header();
    example_array_storage();
    example_fixed_width_types();
    example_endianness();
    example_size_comparison();
    example_read_until_eof();
    example_2d_array();
    example_chunked_format();
    example_database();
    example_error_handling();
    
    printf("╔═══════════════════════════════════════════════════════════════╗\n");
    printf("║                    ALL EXAMPLES COMPLETED                     ║\n");
    printf("╚═══════════════════════════════════════════════════════════════╝\n\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML