1๏ธโฃ What is a file, and why do we need one?
Fast, but forgets everything when the program ends or power goes off. Variables live here.
Slower, but remembers forever. Data is still there next time.
A file is a named place on the disk (hard disk / SSD) where data is stored permanently.
The 3 golden steps: OPEN โ USE โ CLOSE
| Step | C code | Kid meaning |
|---|---|---|
| 0. Make a bookmark | FILE *fp; | A file pointer: a bookmark that remembers which notebook and which page |
| 1. Open | fp = fopen("hello.txt", "w"); | Open the notebook named hello.txt for writing |
| 2. Check | if (fp == NULL) | Could not open it? (missing file, no permission) Then stop! |
| 3. Use | fprintf, fgets, fputc ... | Write or read |
| 4. Close | fclose(fp); | Close the notebook so everything is really saved |
fp == NULL. If you use a NULL file pointer, your program crashes.FILE (all capitals) is a structure defined in <stdio.h>. It stores details like where the cursor is and the buffer. We only use a pointer to it.FILE *fp, open with fopen, check NULL, read/write, close with fclose.File: 01_why_files_first_file.c
/*
* Program 1: Why Files? Your very first file
* ------------------------------------------
* Real-life story: When you switch off a computer, everything in its
* memory (RAM) is forgotten, like writing on a whiteboard and wiping it.
* A FILE is like a notebook: what you write stays there even tomorrow.
*
* Steps to use a file (remember: OPEN -> USE -> CLOSE):
* 1. FILE *fp; -> a "file pointer", like a bookmark for the notebook
* 2. fp = fopen(name, mode) -> open the notebook
* 3. fprintf / fgets ... -> write or read
* 4. fclose(fp) -> close the notebook (very important!)
*/
#include <stdio.h>
int main() {
FILE *fp; /* our bookmark for the file */
/* ---- WRITE into the file ---- */
fp = fopen("hello.txt", "w"); /* "w" = open for writing (makes a new file) */
if (fp == NULL) { /* NULL means "could not open" */
printf("Sorry, could not open the file!\n");
return 1;
}
fprintf(fp, "Hello, I am saved in a file!\n");
fprintf(fp, "I will still be here tomorrow.\n");
fclose(fp); /* close it so the words are really saved */
printf("Wrote 2 lines into hello.txt\n\n");
/* ---- READ it back ---- */
char line[100]; /* a box to hold one line */
fp = fopen("hello.txt", "r"); /* "r" = open for reading */
if (fp == NULL) {
printf("Sorry, could not open the file!\n");
return 1;
}
printf("Reading hello.txt:\n");
while (fgets(line, sizeof(line), fp) != NULL) { /* read one line at a time */
printf(" %s", line);
}
fclose(fp);
return 0;
}
Output
Wrote 2 lines into hello.txt Reading hello.txt: Hello, I am saved in a file! I will still be here tomorrow.
2๏ธโฃ Input & Output: the concept of a file (streams)
C treats everything as a stream of bytes: a file on disk, the keyboard, and the screen. So reading from the keyboard and reading from a file look almost the same!
| Stream | Name | Connected to | Used by |
|---|---|---|---|
stdin | Standard input | Keyboard | scanf, getchar, fgets(.., stdin) |
stdout | Standard output | Screen | printf, putchar |
stderr | Standard error | Screen | fprintf(stderr, ...) for error messages |
fopen them../prog > out.txt), error messages still show on the screen, so you don't miss them. That's also why, in the output below, the stderr message is shown separately.File: 02_streams_stdin_stdout_stderr.c
/*
* Program 2: Concept of a file - Streams (stdin, stdout, stderr)
* --------------------------------------------------------------
* Real-life story: Think of a STREAM as a water pipe.
* Data flows through it, one character after another, like water.
*
* Every C program gets 3 pipes for free, already open:
* stdin -> the INPUT pipe (keyboard) - like your ears
* stdout -> the OUTPUT pipe (screen) - like your mouth
* stderr -> the ERROR pipe (screen, for problems) - like shouting "Help!"
*
* In C, the keyboard and the screen are treated just like files!
* That's why fprintf(stdout, ...) works the same as printf(...).
*
* Sample input: Sabari
*/
#include <stdio.h>
int main() {
char name[50];
fprintf(stdout, "What is your name? "); /* same as printf */
if (fgets(name, sizeof(name), stdin) == NULL) { /* read from the keyboard pipe */
fprintf(stderr, "Error: no name was typed!\n"); /* errors go to stderr */
return 1;
}
fprintf(stdout, "Hello, %s", name); /* name already has the Enter (\n) */
fprintf(stderr, "(This message travelled through the stderr pipe)\n");
return 0;
}
Output (typed input: Sabari)
What is your name? Hello, Sabari --- what came through stderr --- (This message travelled through the stderr pipe)
3๏ธโฃ fopen modes: how do you want to open the notebook?
| Mode | Meaning | If file exists | If file is missing |
|---|---|---|---|
"r" | Read only | Opens, cursor at start | Returns NULL |
"w" | Write only | Wipes it clean (old data lost!) | Creates a new file |
"a" | Append (add at end) | Keeps old data, writes at the end | Creates a new file |
"r+" | Read + write | Opens, keeps data, cursor at start | Returns NULL |
"w+" | Write + read | Wipes it clean | Creates a new file |
"a+" | Read + append | Keeps data, writes always go to end | Creates a new file |
"rb" "wb" "ab""rb+" "wb+" "ab+" | Same as above, but for binary files | Add b when you use fwrite/fread with raw data | |
The file
shopping.txt currently contains:
"w" is dangerous: it erases the file the moment you open it, even if you write nothing.FILE *fopen(const char *filename, const char *mode); Returns a FILE pointer on success, NULL on failure. List all modes r, w, a, r+, w+, a+ (and their binary versions with b) with their behaviour for existing and missing files.File: 03_fopen_modes.c
/*
* Program 3: fopen modes - "w", "a", "r", "r+"
* --------------------------------------------
* Real-life story: A shopping list on the fridge.
* "w" -> tear off the old page and write a NEW list (old list is gone!)
* "a" -> add items at the BOTTOM of the list (append)
* "r" -> only READ the list, no writing
* "r+"-> read AND change the list (file must already exist)
*/
#include <stdio.h>
/* a small helper that prints the whole file */
void showFile(const char *name) {
FILE *fp = fopen(name, "r");
int ch;
if (fp == NULL) {
printf("(cannot open %s)\n", name);
return;
}
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
fclose(fp);
}
int main() {
FILE *fp;
/* "w" : write a fresh list */
fp = fopen("shopping.txt", "w");
if (fp == NULL) return 1;
fprintf(fp, "milk\nbread\n");
fclose(fp);
printf("After \"w\" (new list):\n");
showFile("shopping.txt");
/* "a" : add to the end, old items stay */
fp = fopen("shopping.txt", "a");
if (fp == NULL) return 1;
fprintf(fp, "eggs\n");
fclose(fp);
printf("\nAfter \"a\" (added eggs):\n");
showFile("shopping.txt");
/* "r+" : change the first letter of the file */
fp = fopen("shopping.txt", "r+");
if (fp == NULL) return 1;
fputc('M', fp); /* overwrite 'm' with 'M' */
fclose(fp);
printf("\nAfter \"r+\" (changed m to M):\n");
showFile("shopping.txt");
/* "w" again : WARNING, it wipes everything! */
fp = fopen("shopping.txt", "w");
if (fp == NULL) return 1;
fprintf(fp, "chocolate\n");
fclose(fp);
printf("\nAfter \"w\" again (old list wiped!):\n");
showFile("shopping.txt");
/* "r" on a file that does not exist gives NULL */
fp = fopen("no_such_file.txt", "r");
if (fp == NULL) {
printf("\n\"r\" on a missing file -> fopen gives NULL\n");
}
return 0;
}
Output
After "w" (new list): milk bread After "a" (added eggs): milk bread eggs After "r+" (changed m to M): Milk bread eggs After "w" again (old list wiped!): chocolate "r" on a missing file -> fopen gives NULL
4๏ธโฃ File I/O operations: one character at a time (fputc, fgetc, EOF, feof)
| Function | What it does | Returns |
|---|---|---|
fputc(ch, fp) | Writes one character | The character, or EOF on error |
fgetc(fp) | Reads one character, cursor moves 1 step | The character as an int, or EOF at the end |
feof(fp) | Asks "did we already reach the end?" | Non-zero (true) after the end was hit |
fclose(fp) | Saves and closes the file | 0 on success |
getc / putc | Same as fgetc / fputc |
int ch, not a char.while (!feof(fp)) is a common mistake: feof only becomes true after a read fails, so the last item gets processed twice. Check the return value of the read function instead, like while ((ch = fgetc(fp)) != EOF).File: 04_fputc_fgetc_feof.c
/*
* Program 4: Character I/O - fputc, fgetc, EOF and feof
* ----------------------------------------------------
* Real-life story: Threading beads on a string ONE bead at a time,
* then taking them off one by one until the string is empty.
*
* fputc(ch, fp) -> put ONE character into the file
* fgetc(fp) -> get ONE character from the file
* EOF -> "End Of File", a special signal: no more beads!
* feof(fp) -> asks "did we already reach the end?" (1 = yes)
*/
#include <stdio.h>
int main() {
FILE *fp;
char word[] = "BEADS";
int i, ch;
int letters = 0;
/* write the word one character at a time */
fp = fopen("beads.txt", "w");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
for (i = 0; word[i] != '\0'; i++) {
fputc(word[i], fp); /* thread one bead */
}
fclose(fp);
printf("Saved \"%s\" into beads.txt\n", word);
/* read it back one character at a time */
fp = fopen("beads.txt", "r");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
printf("Taking beads off: ");
while ((ch = fgetc(fp)) != EOF) { /* keep going until End Of File */
printf("[%c] ", ch);
letters++;
}
printf("\nTotal characters = %d\n", letters);
if (feof(fp)) { /* confirm we hit the end */
printf("feof says: yes, we reached the end of the file.\n");
}
fclose(fp);
return 0;
}
Output
Saved "BEADS" into beads.txt Taking beads off: [B] [E] [A] [D] [S] Total characters = 5 feof says: yes, we reached the end of the file.
5๏ธโฃ One line at a time (fputs, fgets)
| Function | What it does |
|---|---|
fputs(str, fp) | Writes the whole string. It does not add \n by itself; you must put it. |
fgets(buf, n, fp) | Reads up to n-1 characters, or until \n. Keeps the \n, adds '\0'. Returns NULL when there are no more lines. |
fgets is safe because you tell it the size of your box. It will never overflow your array.File: 05_fputs_fgets_lines.c
/*
* Program 5: Line I/O - fputs and fgets
* -------------------------------------
* Real-life story: Writing a poem in a notebook LINE by line,
* and then reading it aloud line by line, with line numbers.
*
* fputs(text, fp) -> write a whole string (line)
* fgets(box, size, fp) -> read ONE line (at most size-1 letters)
* gives NULL when there are no more lines
*/
#include <stdio.h>
int main() {
FILE *fp;
char line[100];
int lineNo = 0;
fp = fopen("poem.txt", "w");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
fputs("Twinkle twinkle little star\n", fp);
fputs("How I wonder what you are\n", fp);
fputs("Up above the world so high\n", fp);
fputs("Like a diamond in the sky\n", fp);
fclose(fp);
fp = fopen("poem.txt", "r");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
while (fgets(line, sizeof(line), fp) != NULL) {
lineNo++;
printf("Line %d: %s", lineNo, line);
}
fclose(fp);
printf("\nThe poem has %d lines.\n", lineNo);
return 0;
}
Output
Line 1: Twinkle twinkle little star Line 2: How I wonder what you are Line 3: Up above the world so high Line 4: Like a diamond in the sky The poem has 4 lines.
6๏ธโฃ Formatted I/O (fprintf, fscanf)
You already know printf and scanf. Just put an f in front and give the file pointer first:
| Screen / keyboard | File |
|---|---|
printf("%d %s", roll, name); | fprintf(fp, "%d %s", roll, name); |
scanf("%d %s", &roll, name); | fscanf(fp, "%d %s", &roll, name); |
fscanf returns how many items it read. Reading 3 items per line? Loop while it returns 3. At the end of the file it returns EOF.Roll Name Marks
int fprintf(FILE *fp, const char *format, ...); and int fscanf(FILE *fp, const char *format, ...);File: 06_fprintf_fscanf_marks.c
/*
* Program 6: Formatted I/O - fprintf and fscanf
* ---------------------------------------------
* Real-life story: The teacher's mark register.
* Each line has: roll number, name, marks.
*
* fprintf(fp, "%d %s %d\n", ...) -> like printf, but writes into a FILE
* fscanf (fp, "%d %s %d", ...) -> like scanf, but reads from a FILE
* returns how many items it read
*/
#include <stdio.h>
int main() {
FILE *fp;
int roll, marks;
char name[30];
int total = 0, count = 0;
/* the teacher writes the register */
fp = fopen("marks.txt", "w");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
fprintf(fp, "%d %s %d\n", 1, "Anu", 85);
fprintf(fp, "%d %s %d\n", 2, "Bala", 72);
fprintf(fp, "%d %s %d\n", 3, "Chitra", 94);
fprintf(fp, "%d %s %d\n", 4, "Dinesh", 60);
fclose(fp);
/* the principal reads the register */
fp = fopen("marks.txt", "r");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
printf("Roll Name Marks\n");
printf("---------------------\n");
while (fscanf(fp, "%d %29s %d", &roll, name, &marks) == 3) { /* 3 items read = OK */
printf("%-5d %-9s %d\n", roll, name, marks);
total = total + marks;
count++;
}
fclose(fp);
printf("---------------------\n");
printf("Class average = %.2f\n", (float)total / count);
return 0;
}
Output
Roll Name Marks --------------------- 1 Anu 85 2 Bala 72 3 Chitra 94 4 Dinesh 60 --------------------- Class average = 77.75
7๏ธโฃ Text files vs Binary files
| Text file | Binary file | |
|---|---|---|
| Stores data as | Readable characters (ASCII) | Raw bytes, exactly like in memory |
| Open in Notepad? | Yes, you can read it | Shows strange symbols |
| Size of number 123456789 | 9 bytes | 4 bytes (sizeof int) |
| Newline | May be converted (e.g. \n โ \r\n on Windows) | No conversion |
| End of file | Detected as EOF | Detected by file size / fread return |
| Speed | Slower (number โ text conversion) | Faster (direct copy) |
| Modes | "r" "w" "a" | "rb" "wb" "ab" |
| Functions | fprintf, fscanf, fgets, fputs | fwrite, fread |
| Example | .txt, .c, .html | .dat, .bin, .jpg, .exe |
Number:
File: 07_text_vs_binary.c
/*
* Program 7: Text file vs Binary file
* -----------------------------------
* Real-life story: Saving the number 123456789.
* TEXT file -> writes it like a human: '1','2','3',... (9 letters = 9 bytes)
* you can open it in Notepad and read it.
* BINARY file -> copies the raw memory of the int (always 4 bytes)
* Notepad shows funny symbols, but the computer reads it fast.
*/
#include <stdio.h>
int main() {
int number = 123456789;
FILE *fp;
long textSize, binSize;
/* TEXT */
fp = fopen("number.txt", "w"); /* "w" = text write */
if (fp == NULL) return 1;
fprintf(fp, "%d", number);
textSize = ftell(fp); /* how many bytes written so far */
fclose(fp);
/* BINARY */
fp = fopen("number.bin", "wb"); /* "wb" = binary write */
if (fp == NULL) return 1;
fwrite(&number, sizeof(number), 1, fp); /* copy 1 int straight from memory */
binSize = ftell(fp);
fclose(fp);
printf("Number saved : %d\n", number);
printf("Text file size : %ld bytes (one byte per digit)\n", textSize);
printf("Binary file size : %ld bytes (size of an int)\n", binSize);
/* read the binary number back */
int readBack = 0;
fp = fopen("number.bin", "rb"); /* "rb" = binary read */
if (fp == NULL) return 1;
fread(&readBack, sizeof(readBack), 1, fp);
fclose(fp);
printf("Read back from bin: %d\n", readBack);
/* peek at the raw bytes inside the binary file */
unsigned char bytes[4];
fp = fopen("number.bin", "rb");
if (fp == NULL) return 1;
fread(bytes, 1, 4, fp);
fclose(fp);
printf("Raw bytes in .bin : %02X %02X %02X %02X (not readable by humans!)\n",
bytes[0], bytes[1], bytes[2], bytes[3]);
return 0;
}
Output
Number saved : 123456789 Text file size : 9 bytes (one byte per digit) Binary file size : 4 bytes (size of an int) Read back from bin: 123456789 Raw bytes in .bin : 15 CD 5B 07 (not readable by humans!)
0x075BCD15. Most computers store the smallest byte first. This is called little-endian.8๏ธโฃ Saving whole records: fwrite and fread
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *fp);
size_t fread (void *ptr, size_t size, size_t count, FILE *fp);
โ โ โ
โ โ โโ how many items
โ โโโโโโโโโโโโโโโ size of ONE item (use sizeof)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ address of the data (use &)
while (fread(&s, sizeof s, 1, fp) == 1) reads until no full record is left.File: 08_binary_struct_fwrite_fread.c
/*
* Program 8: Binary file with a structure - fwrite and fread
* ----------------------------------------------------------
* Real-life story: School ID cards. Each card has roll, name and marks.
* Instead of writing each piece separately, we photocopy the WHOLE card
* into the file in one go with fwrite, and read the whole card with fread.
*
* fwrite(&data, size_of_one, how_many, fp)
* fread (&data, size_of_one, how_many, fp) -> returns how many it read
*/
#include <stdio.h>
struct Student {
int roll;
char name[20];
float marks;
};
int main() {
struct Student cls[3] = {
{1, "Anu", 85.5},
{2, "Bala", 72.0},
{3, "Chitra", 94.5}
};
struct Student s;
FILE *fp;
/* write all 3 cards at once */
fp = fopen("students.dat", "wb");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
fwrite(cls, sizeof(struct Student), 3, fp);
fclose(fp);
printf("Saved 3 students. Each record = %zu bytes\n\n", sizeof(struct Student));
/* read them back one card at a time */
fp = fopen("students.dat", "rb");
if (fp == NULL) {
printf("Could not open file\n");
return 1;
}
printf("Roll Name Marks\n");
while (fread(&s, sizeof(struct Student), 1, fp) == 1) { /* 1 card read = OK */
printf("%-5d %-8s %.1f\n", s.roll, s.name, s.marks);
}
fclose(fp);
return 0;
}
Output
Saved 3 students. Each record = 28 bytes Roll Name Marks 1 Anu 85.5 2 Bala 72.0 3 Chitra 94.5
9๏ธโฃ Types of file processing: Sequential vs Random access
To hear song 5, you must play (or fast-forward through) songs 1 to 4. Data is read in order, from start to end.
Tap song 5 and it plays right away. You jump directly to any record using its position.
| Sequential access | Random (direct) access | |
|---|---|---|
| How it reads | One after another, from the beginning | Jump straight to any position |
| Functions | fgetc, fgets, fscanf, fread in a loop | fseek, ftell, rewind + fread/fwrite |
| Record size | Can be different for each record | Usually fixed size (so position = (n-1) ร size) |
| Speed to find record n | Slow for big files | Fast |
| Updating in the middle | Hard (usually rewrite the file) | Easy (seek and overwrite) |
| Example | Diary, log file, poem | Bank accounts, railway seats, student database |
The random access tools
| Function | Meaning |
|---|---|
fseek(fp, offset, origin) | Move the cursor offset bytes from origin. Returns 0 if OK. |
SEEK_SET (0) | Count from the start of the file |
SEEK_CUR (1) | Count from where the cursor is now |
SEEK_END (2) | Count from the end (use a negative offset to go back) |
ftell(fp) | Tells the current cursor position in bytes (a long) |
rewind(fp) | Puts the cursor back at byte 0 (same as fseek(fp, 0, SEEK_SET)) |
The file contains:
fseek(fp, , )
๐ Sequential access file program: My Diary
"a"), and you read from page 1 onwards. To find Wednesday, you have to go past Monday and Tuesday first.Steps: create the file โ append records one after another โ open in "r" and read in a loop until the end.
File: 09_sequential_access_diary.c
/*
* Program 9: SEQUENTIAL ACCESS file - My Diary
* --------------------------------------------
* Real-life story: A diary. You always WRITE on the next empty page
* (append), and you READ from page 1, then page 2, then page 3...
* You can't jump. Like watching a movie from the start.
*
* Sequential access = go through the file in order, from start to end.
*/
#include <stdio.h>
void addEntry(const char *day, const char *note) {
FILE *fp = fopen("diary.txt", "a"); /* "a" = add at the end, keep old pages */
if (fp == NULL) {
printf("Could not open diary\n");
return;
}
fprintf(fp, "%s: %s\n", day, note);
fclose(fp);
}
int main() {
FILE *fp;
char line[120];
int page = 0;
/* start with an empty diary for this demo */
fp = fopen("diary.txt", "w");
if (fp == NULL) return 1;
fclose(fp);
/* write entries, one after another */
addEntry("Monday", "Learned for loops");
addEntry("Tuesday", "Played cricket, we won!");
addEntry("Wednesday", "Learned about files in C");
/* read the diary from the first page to the last */
fp = fopen("diary.txt", "r");
if (fp == NULL) return 1;
printf("=== My Diary ===\n");
while (fgets(line, sizeof(line), fp) != NULL) {
page++;
printf("Page %d -> %s", page, line);
}
fclose(fp);
/* search: to find Wednesday we MUST read Monday and Tuesday first */
fp = fopen("diary.txt", "r");
if (fp == NULL) return 1;
page = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
page++;
if (line[0] == 'W') {
printf("\nFound Wednesday on page %d (had to read %d pages before it)\n",
page, page - 1);
break;
}
}
fclose(fp);
return 0;
}
Output
=== My Diary === Page 1 -> Monday: Learned for loops Page 2 -> Tuesday: Played cricket, we won! Page 3 -> Wednesday: Learned about files in C Found Wednesday on page 3 (had to read 2 pages before it)
1๏ธโฃ1๏ธโฃ Random access file program: Bank Passbook
Every record has the same size, so record N starts at byte (N - 1) ร sizeof(record).
Record size (bytes): Account number:
"rb+" lets us read and overwrite records without wiping the file. That's the key to updating.File: 10_random_access_passbook.c
/*
* Program 10: RANDOM ACCESS file - Bank Passbook
* ----------------------------------------------
* Real-life story: A bank has many account records saved in a file.
* The cashier wants account number 3. Instead of reading 1, 2, 3...
* she JUMPS straight to record 3. Like skipping to a song on a playlist!
*
* fseek(fp, offset, from) -> move the file "cursor"
* from = SEEK_SET (start), SEEK_CUR (where I am), SEEK_END (end)
* ftell(fp) -> tells where the cursor is (in bytes)
* rewind(fp) -> go back to the very beginning
*
* Record N starts at byte: (N - 1) * sizeof(record)
*/
#include <stdio.h>
struct Account {
int number;
char name[20];
float balance;
};
int main() {
struct Account all[5] = {
{1, "Anu", 5000},
{2, "Bala", 1200},
{3, "Chitra", 9800},
{4, "Dinesh", 300},
{5, "Esha", 7100}
};
struct Account a;
FILE *fp;
int want;
long size = sizeof(struct Account);
/* create the bank file */
fp = fopen("bank.dat", "wb");
if (fp == NULL) return 1;
fwrite(all, size, 5, fp);
fclose(fp);
fp = fopen("bank.dat", "rb+"); /* read AND write, binary */
if (fp == NULL) return 1;
/* 1. Jump straight to account 3 */
want = 3;
fseek(fp, (want - 1) * size, SEEK_SET);
printf("Cursor jumped to byte %ld\n", ftell(fp));
fread(&a, size, 1, fp);
printf("Account %d: %s has Rs %.2f\n", a.number, a.name, a.balance);
printf("After reading, cursor is at byte %ld\n\n", ftell(fp));
/* 2. Deposit Rs 500 into account 3 and save it back in the same place */
a.balance = a.balance + 500;
fseek(fp, (want - 1) * size, SEEK_SET); /* go back to the start of record 3 */
fwrite(&a, size, 1, fp);
printf("Deposited Rs 500 into account %d\n\n", want);
/* 3. Jump to the LAST record using SEEK_END */
fseek(fp, -size, SEEK_END); /* one record back from the end */
fread(&a, size, 1, fp);
printf("Last account: %d %s Rs %.2f\n", a.number, a.name, a.balance);
/* total file size */
fseek(fp, 0, SEEK_END);
printf("File size = %ld bytes = %ld records\n\n", ftell(fp), ftell(fp) / size);
/* 4. rewind and print everything */
rewind(fp);
printf("After rewind, cursor is at byte %ld\n", ftell(fp));
printf("All accounts:\n");
while (fread(&a, size, 1, fp) == 1) {
printf(" %d %-7s Rs %.2f\n", a.number, a.name, a.balance);
}
fclose(fp);
return 0;
}
Output
Cursor jumped to byte 56 Account 3: Chitra has Rs 9800.00 After reading, cursor is at byte 84 Deposited Rs 500 into account 3 Last account: 5 Esha Rs 7100.00 File size = 140 bytes = 5 records After rewind, cursor is at byte 0 All accounts: 1 Anu Rs 5000.00 2 Bala Rs 1200.00 3 Chitra Rs 10300.00 4 Dinesh Rs 300.00 5 Esha Rs 7100.00
1๏ธโฃ2๏ธโฃ Command line arguments
int main(int argc, char *argv[])
โ โ
โ โโโ ARGument Vector: an array of strings (the words typed)
โโโโโโโโโโโโโโโโ ARGument Count: how many words, including the program name
"10" is text, not a number. Use atoi() (to int) or atof() (to float) from <stdlib.h> to convert.argv[0] is always the program's own name. Real arguments start at argv[1]. argv[argc] is NULL.Program A: add the numbers you type
File: 11_command_line_sum.c
/*
* Program 11: Command Line Arguments - add numbers
* ------------------------------------------------
* Real-life story: Ordering at a shop counter. Instead of the shopkeeper
* ASKING you questions later (scanf), you tell everything at once
* while walking in: ./sum 10 20 30
*
* int main(int argc, char *argv[])
* argc -> ARGument Count: how many words were typed (program name included)
* argv -> ARGument Vector: the words themselves, as strings
*
* ./sum 10 20 30
* argv[0] = "./sum" argv[1] = "10" argv[2] = "20" argv[3] = "30"
* argc = 4
*
* Run: gcc 11_command_line_sum.c -o sum
* ./sum 10 20 30
*/
#include <stdio.h>
#include <stdlib.h> /* for atoi: turns "10" (text) into 10 (number) */
int main(int argc, char *argv[]) {
int i, total = 0;
printf("argc = %d\n", argc);
for (i = 0; i < argc; i++) {
printf("argv[%d] = \"%s\"\n", i, argv[i]);
}
if (argc < 2) {
printf("\nPlease give some numbers, like: %s 10 20 30\n", argv[0]);
return 1;
}
for (i = 1; i < argc; i++) { /* start at 1, because argv[0] is the program name */
total = total + atoi(argv[i]);
}
printf("\nSum of the numbers = %d\n", total);
return 0;
}
Run commands and output
$ gcc 11_command_line_sum.c -o sum $ ./sum 10 20 30 argc = 4 argv[0] = "./sum" argv[1] = "10" argv[2] = "20" argv[3] = "30" Sum of the numbers = 60 $ ./sum argc = 1 argv[0] = "./sum" Please give some numbers, like: ./sum 10 20 30
Program B: copy a file named on the command line
File: 12_command_line_copy_file.c
/*
* Program 12: Command Line Arguments - copy a file
* ------------------------------------------------
* Real-life story: A photocopy machine. You say which page to copy
* and where to put the copy: ./copy poem.txt poem_copy.txt
*
* argv[1] -> the file to copy FROM (source)
* argv[2] -> the file to copy TO (destination)
*
* Run: gcc 12_command_line_copy_file.c -o copy
* ./copy poem.txt poem_copy.txt
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *src, *dest;
int ch;
long count = 0;
if (argc != 3) { /* need exactly: program, source, destination */
printf("Usage: %s source_file destination_file\n", argv[0]);
return 1;
}
src = fopen(argv[1], "r");
if (src == NULL) {
printf("Cannot open source file \"%s\"\n", argv[1]);
return 1;
}
dest = fopen(argv[2], "w");
if (dest == NULL) {
printf("Cannot create destination file \"%s\"\n", argv[2]);
fclose(src);
return 1;
}
while ((ch = fgetc(src)) != EOF) { /* copy one character at a time */
fputc(ch, dest);
count++;
}
fclose(src);
fclose(dest);
printf("Copied %ld characters from \"%s\" to \"%s\"\n", count, argv[1], argv[2]);
return 0;
}
Run commands and output (poem.txt was made by program 5)
$ gcc 12_command_line_copy_file.c -o copy $ ./copy poem.txt poem_copy.txt Copied 107 characters from "poem.txt" to "poem_copy.txt" $ cat poem_copy.txt Twinkle twinkle little star How I wonder what you are Up above the world so high Like a diamond in the sky $ ./copy missing.txt x.txt Cannot open source file "missing.txt" $ ./copy Usage: ./copy source_file destination_file
argc (count) and argv (array of strings). argv[0] is the program name. Write a program to copy one file to another using command line arguments (Program B is the classic 16-mark answer).๐ 2-mark questions & answers
1. What is a file?
A file is a named collection of related data stored permanently on secondary storage (disk). It keeps data even after the program ends.2. Why do we need files?
Variables lose their data when the program ends. Files store data permanently, can hold large amounts of data, and let different programs share data.3. What is a file pointer?
A pointer of typeFILE * that points to a FILE structure holding information about an opened file (buffer, cursor position, mode). Example: FILE *fp;4. What is a stream? Name the standard streams.
A stream is a sequence of bytes flowing between a program and a device or file. Standard streams: stdin (keyboard), stdout (screen), stderr (screen, errors).5. Difference between "w" and "a" mode?
"w" erases an existing file and writes from the start. "a" keeps the old contents and adds new data at the end. Both create the file if it is missing.6. What does fopen return if the file cannot be opened?
It returns NULL. We must checkif (fp == NULL) before using the file.7. What is EOF?
EOF (End Of File) is a constant (usually -1) defined in stdio.h, returned by input functions like fgetc when there is no more data.8. What is the use of fclose()?
It flushes the buffer (actually saves pending data), releases the file, and frees resources. It returns 0 on success, EOF on error.9. Give two differences between text and binary files.
Text files store data as readable ASCII characters; binary files store raw bytes as in memory. Text files may convert newlines; binary files do no conversion and are usually smaller and faster.10. What is the purpose of fseek()?
It moves the file position indicator to a given offset from SEEK_SET (start), SEEK_CUR (current) or SEEK_END (end). Syntax:fseek(fp, offset, origin);11. What do ftell() and rewind() do?
ftell(fp) returns the current position of the file pointer in bytes. rewind(fp) moves the file pointer back to the beginning of the file.12. What are command line arguments?
Values passed to a program when it is run from the terminal. They arrive inmain(int argc, char *argv[]): argc is the count and argv is the array of argument strings.13. What is argv[0]?
The name of the program itself (as typed to run it).14. Sequential vs random access?
Sequential access reads records one after another from the beginning. Random access jumps directly to any record using fseek.15. What do fread and fwrite return?
The number of complete items successfully read or written. If it's less than requested, the end of file was reached or an error happened.๐ Mini quiz
๐ฏ Practice homework
- Write a program that counts the characters, words and lines in
poem.txt. - Ask the user for 3 friends' names and phone numbers, and save them to
contacts.txtusing fprintf. Then read them back with fscanf. - Change program 10 so the user types an account number and an amount to withdraw. Don't allow the balance to go below 0.
- Write
./upper in.txt out.txt: copy a file but turn every letter into CAPITALS (hint:toupperfrom<ctype.h>). - Use fseek and ftell to find the size of any file given on the command line.
- Write a program that reads
students.dat(from program 8) and prints only the students with marks above 80.