Reading and Writing Files
fprintf, fscanf, fgetc, and fputc.
5 minute read
Big idea
File functions mirror the ones you know: fprintf/fscanf are printf/scanf for files, and fgetc/fputc read and write one character at a time.
Formatted: fprintf and fscanf
They take the FILE * first, then exactly what printf/scanf take:
fprintf(f, "%s %d\n", name, score);
fscanf(f, "%s %d", name, &score);
fscanf returns how many values it read β 2 above when a line parsed fine, and EOF (a negative number) at the end of the file. That makes a natural loop condition:
#include <stdio.h>
int main(void) {
FILE *f = fopen("scores.txt", "w");
if (f == NULL) return 1;
fprintf(f, "asha 88\n");
fprintf(f, "ben 72\n");
fprintf(f, "chen 95\n");
fclose(f);
f = fopen("scores.txt", "r");
if (f == NULL) return 1;
char name[20];
int score, total = 0, count = 0;
while (fscanf(f, "%19s %d", name, &score) == 2) {
printf("%s: %d\n", name, score);
total += score;
count++;
}
fclose(f);
printf("Average: %d\n", total / count);
return 0;
}output
asha: 88
ben: 72
chen: 95
Average: 85Run and edit it in the app.
Watch it
Character by character: fgetc and fputc
fgetc(f) returns the next character β as an int, so it can also return EOF when the file runs out. Store it in an int, not a char:
#include <stdio.h>
int main(void) {
FILE *f = fopen("poem.txt", "w");
if (f == NULL) return 1;
fputs("Roses are red\nViolets are blue\nC is fun\n", f);
fclose(f);
f = fopen("poem.txt", "r");
if (f == NULL) return 1;
int c, lines = 0, chars = 0;
while ((c = fgetc(f)) != EOF) {
chars++;
if (c == '\n') lines++;
}
fclose(f);
printf("%d lines, %d characters\n", lines, chars);
return 0;
}output
3 lines, 40 charactersRun and edit it in the app.
(c = fgetc(f)) != EOF does two things: stores the next character in c, then checks it. The brackets matter β without them, != would run first.
Appending
Opening in "a" mode adds to the end instead of erasing:
#include <stdio.h>
int main(void) {
FILE *f = fopen("log.txt", "w");
fputs("one\n", f);
fclose(f);
f = fopen("log.txt", "a");
fputs("two\n", f);
fclose(f);
f = fopen("log.txt", "w");
fputs("three\n", f);
fclose(f);
f = fopen("log.txt", "r");
char line[20];
while (fgets(line, sizeof line, f) != NULL) {
printf("%s", line);
}
fclose(f);
return 0;
}What does it print? Show the answer
threeRun and edit it in the app.
The last "w" erased everything written before it.
Think of it like
A diary. fprintf writes a formatted entry; fscanf reads entries back in the same format; fgetc reads one letter at a time, like tracing the page with your finger.
π·οΈ Spidey-sense: My patrol log:
fprintf(log, "%s %d\n", villain, hour);every night in"a"mode. One morning I opened it in"w"β three years of notes, gone. Now I trust"a".
Key terms
fprintf/fscanfβ Formatted write / read on a file.fgetc/fputc/fputsβ Read a character / write a character / write a string.- EOF β "End of file": the value returned when there's nothing left to read.
Check yourself
Which writes formatted text to a file?
Why store fgetc's result in an int, not a char?
fscanf(f, "%d %d", &a, &b) returns 2 whenβ¦