Programming Language & Its Applications — Pointers, Structure and Data Files in C, NEC licence examination syllabus (Nepal Engineering Council).
Programs that forget everything when they close are toys. Files are how software remembers.
Everything so far has lived in RAM and vanished at return 0. Files give your program persistence. C's model is deliberately simple: open a stream, read or write through it, close it. The FILE* handle you get back hides all the operating-system detail, and the same six functions work on a text file, a device, or a pipe.
.env file, a CSV export from Excel, the log file that tells a sysadmin why the server crashed at 3 a.m., the SQLite database behind your phone's WhatsApp history — all of them are opened, read, and written with exactly these calls or their equivalents in other languages. When a program says "corrupted file", it usually means someone forgot fclose and the buffer never reached the disk. You are about to learn why that happens."w" destroys the file's contents the instant you open it — before you write a single byte. Opening a file you meant to read with the wrong mode letter is how people lose data. If you want to add to a file, the mode is "a".
#include <stdio.h>
#include <string.h>
int main(void) {
/* WRITE */
FILE *fp = fopen("marks.txt", "w");
if (!fp) { perror("marks.txt"); return 1; }
fprintf(fp, "101 Ram 87.5\n");
fprintf(fp, "102 Sita 91.0\n");
fprintf(fp, "103 Hari 76.5\n");
fclose(fp); /* flushes the buffer to disk */
/* APPEND - does not destroy what is there */
fp = fopen("marks.txt", "a");
fprintf(fp, "104 Gita 68.0\n");
fclose(fp);
/* READ line by line */
fp = fopen("marks.txt", "r");
if (!fp) return 1;
char line[128];
int lines = 0;
printf("--- fgets ---\n");
while (fgets(line, sizeof line, fp)) {
line[strcspn(line, "\n")] = '\0';
printf("%2d | %s\n", ++lines, line);
}
/* READ with fscanf into variables */
rewind(fp); /* back to the start */
printf("--- fscanf ---\n");
int roll; char name[20]; float m; float total = 0; int n = 0;
while (fscanf(fp, "%d %19s %f", &roll, name, &m) == 3) {
printf("%d %-8s %.1f\n", roll, name, m);
total += m; n++;
}
printf("average = %.2f over %d records\n", total/n, n);
fclose(fp);
return 0;
}
Output:
--- fgets ---
1 | 101 Ram 87.5
2 | 102 Sita 91.0
3 | 103 Hari 76.5
4 | 104 Gita 68.0
--- fscanf ---
101 Ram 87.5
102 Sita 91.0
103 Hari 76.5
104 Gita 68.0
average = 80.75 over 4 records
#include <stdio.h>
int main(void) {
FILE *in = fopen("marks.txt", "r");
if (!in) { perror("open in"); return 1; }
FILE *out = fopen("copy.txt", "w");
if (!out) { perror("open out"); fclose(in); return 1; }
long chars = 0, lines = 0, words = 0;
int c, in_word = 0;
while ((c = fgetc(in)) != EOF) { /* note: int c */
fputc(c, out);
chars++;
if (c == '\n') lines++;
if (c == ' ' || c == '\n' || c == '\t') in_word = 0;
else if (!in_word) { in_word = 1; words++; }
}
fclose(in); fclose(out);
printf("chars=%ld words=%ld lines=%ld\n",
chars, words, lines);
return 0;
}
Output:
chars=76 words=12 lines=4
That int c matters. Declare it char c and on a platform where char is unsigned, c != EOF is always true — the loop never ends. Where char is signed, a legitimate byte 0xFF reads as −1 and the loop stops early, truncating your copy. This is the same trap as in the unformatted-I/O topic, and it is the kind of bug that only shows up on someone else's machine.
#include <stdio.h>
#include <string.h>
typedef struct {
int roll;
char name[20];
float marks;
} Student; /* 28 bytes */
int main(void) {
Student in[3] = {
{101, "Ram Bahadur", 87.5f},
{102, "Sita Devi", 91.0f},
{103, "Hari Prasad", 76.5f}
};
/* write all three in ONE call */
FILE *fp = fopen("students.dat", "wb");
if (!fp) return 1;
size_t w = fwrite(in, sizeof(Student), 3, fp);
printf("wrote %zu records (%zu bytes)\n",
w, w * sizeof(Student));
fclose(fp);
/* read them back */
Student out[3];
fp = fopen("students.dat", "rb");
size_t r = fread(out, sizeof(Student), 3, fp);
printf("read %zu records\n", r);
for (size_t i = 0; i < r; i++)
printf(" %d %-14s %.1f\n",
out[i].roll, out[i].name, out[i].marks);
/* file size from the stream */
fseek(fp, 0, SEEK_END);
printf("file size = %ld bytes = %ld records\n",
ftell(fp), ftell(fp)/(long)sizeof(Student));
fclose(fp);
return 0;
}
Output:
wrote 3 records (84 bytes)
read 3 records
101 Ram Bahadur 87.5
102 Sita Devi 91.0
103 Hari Prasad 76.5
file size = 84 bytes = 3 records
#include <stdio.h>
int main(void) {
FILE *fp = fopen("log.txt", "w");
if (!fp) return 1;
fprintf(fp, "step 1 done\n");
/* at this instant log.txt is still EMPTY on disk */
fflush(fp); /* force it out NOW */
/* now a crash would still preserve step 1 */
fprintf(fp, "step 2 done\n");
fclose(fp); /* flush + release the handle */
/* forgetting fclose leaks a file descriptor.
A long-running server that leaks them eventually
fails with "Too many open files" (EMFILE). */
return 0;
}
Output: (no console output; check log.txt)
step 1 done
step 2 done
fclose hands your bytes to the operating system, but the OS has its own page cache and may still not have touched the physical disk. That is what fsync() is for, and it is why databases are slower than you expect: PostgreSQL must fsync its write-ahead log before it can honestly say "transaction committed". Search for "fsync and the write-ahead log" if you want to see how a real database turns this one system call into a durability guarantee."w" truncates and "a" appends. Always show the if (fp == NULL) check; marks are lost for omitting it. Standard programs: copy a file, count characters/words/lines, write and read a student record file. Know that fgetc returns int because of EOF, that fwrite/fread return an item count, and be ready to compare text vs binary files on size, portability and parsing cost.Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loading…