Back to blog
Backend Systemsbeginner

C File I/O & the Standard Library

Read and write files in C using fopen, fread, fwrite, and fprintf. Explore the C standard library: string functions, math, time, and random numbers.

Asma HafeezApril 17, 20265 min read
cfile-iostdiostdlibstandard-library
Share:𝕏

C File I/O & the Standard Library

C's standard library provides functions for file I/O, string manipulation, math, and more — all via #include.


Opening and Closing Files

C
#include <stdio.h>

FILE* file = fopen("data.txt", "r");  // open for reading
if (file == NULL) {
    perror("Failed to open file");  // prints error message
    return 1;
}

// ... use the file ...

fclose(file);  // always close when done

File Modes

| Mode | Meaning | |------|---------| | "r" | Read (file must exist) | | "w" | Write (creates or truncates) | | "a" | Append (creates if needed) | | "r+" | Read + write (file must exist) | | "w+" | Read + write (creates or truncates) | | "rb", "wb" | Binary mode versions |


Reading Text Files

C
#include <stdio.h>

// Read line by line
void read_lines(const char* path) {
    FILE* f = fopen(path, "r");
    if (!f) { perror(path); return; }

    char line[256];
    int  line_num = 1;
    while (fgets(line, sizeof(line), f) != NULL) {
        // fgets keeps the newline — strip it
        line[strcspn(line, "\n")] = '\0';
        printf("%3d: %s\n", line_num++, line);
    }
    fclose(f);
}

// Read single characters
int count_chars(const char* path) {
    FILE* f = fopen(path, "r");
    if (!f) return -1;
    int count = 0, ch;
    while ((ch = fgetc(f)) != EOF) count++;
    fclose(f);
    return count;
}

// Read entire file into buffer
char* read_file(const char* path) {
    FILE* f = fopen(path, "rb");
    if (!f) return NULL;

    fseek(f, 0, SEEK_END);       // seek to end
    long size = ftell(f);         // get position = size
    rewind(f);                    // back to beginning

    char* buf = malloc(size + 1);
    if (!buf) { fclose(f); return NULL; }

    fread(buf, 1, size, f);
    buf[size] = '\0';             // null-terminate
    fclose(f);
    return buf;  // caller must free!
}

Writing Text Files

C
// Write formatted text
void write_report(const char* path, int count, double avg) {
    FILE* f = fopen(path, "w");
    if (!f) { perror(path); return; }

    fprintf(f, "=== Report ===\n");
    fprintf(f, "Count:   %d\n", count);
    fprintf(f, "Average: %.2f\n", avg);

    fclose(f);
}

// Append to log file
void log_message(const char* path, const char* msg) {
    FILE* f = fopen(path, "a");
    if (!f) return;

    time_t now = time(NULL);
    char timestamp[30];
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));

    fprintf(f, "[%s] %s\n", timestamp, msg);
    fclose(f);
}

Binary Files

C
typedef struct {
    char   name[50];
    int    age;
    double gpa;
} Student;

// Write binary
void save_students(const char* path, Student* students, int n) {
    FILE* f = fopen(path, "wb");
    if (!f) return;
    fwrite(&n, sizeof(int), 1, f);            // write count
    fwrite(students, sizeof(Student), n, f);  // write all students
    fclose(f);
}

// Read binary
Student* load_students(const char* path, int* out_count) {
    FILE* f = fopen(path, "rb");
    if (!f) return NULL;

    int n;
    fread(&n, sizeof(int), 1, f);

    Student* students = malloc(n * sizeof(Student));
    if (!students) { fclose(f); return NULL; }

    fread(students, sizeof(Student), n, f);
    fclose(f);

    *out_count = n;
    return students;  // caller must free!
}

String Functions (<string.h>)

C
#include <string.h>

char s1[] = "Hello, World!";
char s2[100];

strlen(s1);                    // 13 — length without null terminator
strcpy(s2, s1);                // copy s1 into s2
strncpy(s2, s1, 5);           // copy at most 5 chars (safer)
s2[5] = '\0';                  // ensure null terminator

strcat(s2, " C!");             // append " C!" to s2
strncat(s2, s1, 3);           // append at most 3 chars

strcmp("apple", "banana");     // negative (a < b)
strncmp("abc", "abd", 2);     // 0 — first 2 chars equal

strstr(s1, "World");           // pointer to "World" in s1, or NULL
strchr(s1, 'W');               // pointer to first 'W', or NULL
strtok(s1, ",");               // tokenize (modifies string!)

// Convert case (character by character)
#include <ctype.h>
char ch = 'a';
char upper = toupper(ch);      // 'A'
int  isalpha = isalpha(ch);    // 1 (true)
int  isdigit = isdigit('5');   // 1 (true)

Math Functions (<math.h>)

C
#include <math.h>
// Link with: gcc ... -lm

double x = 2.0;

sqrt(x);          // 1.414...
pow(x, 10);       // 1024.0
fabs(-3.14);      // 3.14 (absolute value)
floor(3.7);       // 3.0
ceil(3.2);        // 4.0
round(3.5);       // 4.0
log(M_E);         // 1.0 (natural log)
log10(100);       // 2.0
sin(M_PI / 2);    // 1.0
cos(0.0);         // 1.0

Random Numbers (<stdlib.h>)

C
#include <stdlib.h>
#include <time.h>

// Seed with current time for different results each run
srand((unsigned int)time(NULL));

// Random int in range [min, max]
int random_int(int min, int max) {
    return min + rand() % (max - min + 1);
}

// Roll a die
int die = random_int(1, 6);

// Random double in [0, 1)
double random_double(void) {
    return (double)rand() / ((double)RAND_MAX + 1.0);
}

String Conversion (<stdlib.h>)

C
// String to number
int    n = atoi("42");           // 42
double d = atof("3.14");         // 3.14
long   l = strtol("100", NULL, 10); // 100 (base 10)

// Number to string
char buf[32];
sprintf(buf, "%d", 42);          // "42"
snprintf(buf, sizeof(buf), "%.2f", 3.14159); // "3.14" (safer)

Key Takeaways

  1. Always check fopen return value — it returns NULL if the file can't be opened
  2. Always fclose — unclosed files may not flush their buffer
  3. Use fgets instead of gets (buffer overflow) and snprintf instead of sprintf
  4. Binary I/O with fread/fwrite is fast but platform-specific (endianness, struct padding)
  5. Strip the newline from fgets results: line[strcspn(line, "\n")] = '\0'

Enjoyed this article?

Explore the Backend Systems learning path for more.

Found this helpful?

Share:𝕏

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.