C

File I/O & Standard Library

Every C program so far has printed to the screen and read from the keyboard — both are, underneath, just special cases of a more general idea: a stream you can read from or write to. This chapter covers reading and writing actual files on disk, plus a tour of the wider standard library beyond stdio.h worth knowing by name.

Quick reference
What it is
The FILE*-based API (fopen, fread, fwrite, fclose) for reading and writing files, plus the rest of C's standard library.
Mental model
A file, once opened, behaves like a one-directional (or two-directional) hose — you read bytes out of it or write bytes into it, in order, tracked by an internal position that advances as you go.
Key numbers
Every successful fopen must be matched by exactly one fclose — a leaked, never-closed file handle is a real, accumulating resource leak.
Reach for it when
Persisting data across program runs (logs, config, saved state) — anything that needs to survive after the program exits.

Opening, using, and closing a file

#include <stdio.h>

int main(void) {
    FILE *f = fopen("log.txt", "w");   // open for writing
    if (f == NULL) {
        printf("Failed to open file\n");
        return 1;
    }

    fprintf(f, "Reading: %d\n", 42);   // works just like printf, but to a file
    fclose(f);                          // ALWAYS close what you open
    return 0;
}
A file's lifecycle: fopen returns a FILE pointer, which is used for one or more reads or writes, then fclose releases it fopen() fread() / fwrite() / fprintf() repeat as many times as needed fclose() If fopen returns NULL, skip straight to error handling — there's nothing valid to close
Every path through this sequence has to end in fclose — including the error path, if the file was actually opened before something else failed.

File modes

ModeMeaning
"r"Read — fails (NULL) if the file doesn't exist.
"w"Write — creates the file if missing, erases existing contents if present.
"a"Append — creates the file if missing, writes are added to the end without erasing.
"rb", "wb"Same as above, but binary mode — no text-mode newline translation.

Reading and writing

// Writing raw bytes
FILE *f = fopen("data.bin", "wb");
int values[3] = {10, 20, 30};
fwrite(values, sizeof(int), 3, f);   // write 3 ints
fclose(f);

// Reading them back
FILE *in = fopen("data.bin", "rb");
int loaded[3];
fread(loaded, sizeof(int), 3, in);   // read 3 ints
fclose(in);

// Line-by-line text reading
FILE *log = fopen("log.txt", "r");
char line[256];
while (fgets(line, sizeof(line), log) != NULL) {
    printf("%s", line);
}
fclose(log);

fread/fwrite move raw bytes and are the natural fit for binary data; fgets/fprintf work at the level of text and lines, the natural fit for human-readable files.

A tour of the wider standard library

Introduction to C listed these headers by name; here's what actually lives in the ones beyond stdio.h and string.h:

stdlib.h
atoi/atof (string-to-number), rand/srand (pseudo-random numbers), exit (terminate immediately), malloc/free (covered fully in Embedded C's Dynamic Memory).
math.h
sqrt, pow, fabs, sin/cos/tan, floor/ceil — floating-point math the language itself has no built-in operators for.
ctype.h
isdigit, isalpha, isspace (character classification), toupper/tolower (case conversion) — one character at a time.
time.h
time (current time), clock (CPU time elapsed) — the basis for timestamps and simple performance measurement.

Real-world applications

Gotchas

Field notes