A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
Every file operation in C starts with fopen and ends with fclose. Between those two calls, you read and write through a FILE pointer, which is an opaque struct managed by the standard library. You never touch its internals. You call functions that accept it. If fopen returns NULL, the file could not be opened. Every subsequent operation on that NULL pointer is undefined behavior. Check the return value. Every single time. No exceptions.
#include <stdio.h>int main(void) {FILE *fp = fopen("notes.txt", "w");if (fp == NULL) {perror("fopen failed");return 1;}fputc('H', fp);fputc('i', fp);fputc('\n', fp);fputs("Second line of notes.\n", fp);fclose(fp);printf("File written successfully.\n");return 0;}
The "w" mode creates the file if it does not exist, or truncates it to zero length if it does. If you want to append, use "a". If you want to read, use "r". If the file must exist for reading and it does not, fopen returns NULL. The perror call prints the system error message (like "No such file or directory") to stderr, which is far more useful than a generic "error occurred" message.
#include <stdio.h>int main(void) {FILE *fp = fopen("notes.txt", "r");if (fp == NULL) {perror("fopen failed");return 1;}int ch;while ((ch = fgetc(fp)) != EOF) {putchar(ch);}fclose(fp);return 0;}
fgetc returns int, not char. This is the same reasoning as getchar: it must be able to represent EOF, which is -1 and cannot fit in an unsigned char. The while loop reads one byte at a time until EOF. For small files this is fine. For large files, buffered reads with fread are faster, but the logic is the same.
| Mode | Meaning | File must exist? | Truncates? |
|---|---|---|---|
| "r" | Read only | Yes | No |
| "w" | Write only | No (creates) | Yes |
| "a" | Append | No (creates) | No |
| "r+" | Read and write | Yes | No |
| "w+" | Read and write | No (creates) | Yes |
| "rb" | Read binary | Yes | No |
On Windows, text mode translates \n to \r\n on write and \r\n to \n on read. Binary mode ("rb", "wb") disables this translation. If you are writing binary data (images, structs, network packets), always use binary mode. Forgetting the 'b' on Windows corrupts binary files silently.
File I/O is where C programs stop being toys and start being tools. Every logger, every config parser, every data pipeline starts with fopen. We cover fseek, rewind, binary I/O, and the rest of the file API in the following lessons. Next: rewind, which resets the file position to the beginning without closing and reopening.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.