C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
82: Opening and Closing Files with fopen/fclose
I've been thinking about that little game project we discussed. Right now, every time we restart the program, the player's high score resets to zero. That's annoying. We need a way to keep that score on the disk so it persists. In C, we don't just "save a variable"; we have to interact with the file system using a file pointer.
Trying to save a high score
Let's start simple. I'll try to open a file called highscore.txt and write a number to it. I know I need fopen, which gives me a FILE * (a pointer to a file structure). I'll just toss the score in there and call it a day.
#include <stdio.h>
int main() {
FILE *fptr;
int score = 1500;
fptr = fopen("highscore.txt", "w");
fprintf(fptr, "%d", score);
return 0;
}
I ran this, and it didn't crash. I checked the folder, and highscore.txt exists and contains "1500". Seems easy, right? But here is where we run into a problem. I tried to run it again, but I noticed something strange: if I had a bunch of other data in that file, it was completely gone. The "w" mode just wiped everything out the moment I opened it. That's a dangerous way to handle data if you aren't careful.
The "It didn't actually save" mystery
Now, let's say I change the code to write a larger amount of data—maybe a whole list of player stats. I noticed that if the program crashes or I force-quit it immediately after the fprintf, the file is sometimes empty or corrupted. Why?
It's because of buffering. C doesn't actually write to the disk the very millisecond you call fprintf; it stores the data in a temporary buffer in memory to make things faster. The data only actually hits the disk when the buffer fills up or when we explicitly tell the system we're done. That's where fclose comes in. I forgot it in my first snippet. Let's fix that.
#include <stdio.h>
int main() {
FILE *fptr;
int score = 1500;
fptr = fopen("highscore.txt", "w");
if (fptr != NULL) {
fprintf(fptr, "%d", score);
fclose(fptr); // This flushes the buffer and releases the file
}
return 0;
}
By adding fclose(fptr), I'm telling the OS, "I'm finished with this file, go ahead and commit everything to the physical drive." If you leave files open, you're leaking system resources, and you're gambling with your data.
Handling the "What if it fails?" scenario
I just tried to run this on a directory where I didn't have write permissions, and the program crashed with a segmentation fault. I looked at the code and realized I was calling fprintf on fptr even if fopen failed. If fopen can't open the file, it returns NULL. Trying to write to NULL is a great way to crash your app.
You'll see a lot of C programmers do a "NULL check" immediately after opening. It's not optional; it's a necessity. I've added that check in the snippet above, but let's look at the logic: if fptr is NULL, we shouldn't even attempt to use it.
Deciding how to open the file
Earlier, I mentioned that "w" wipes the file. I spent a few minutes experimenting with the mode strings to see what actually happens. Here is what I found:
"w"(Write): Creates an empty file. If the file already exists, its contents are destroyed. Use this for fresh saves."r"(Read): Opens an existing file. If the file doesn't exist,fopenreturnsNULL. You can't write to this."a"(Append): Opens a file and moves the cursor to the very end. If the file doesn't exist, it creates it. This is perfect for log files where you want to keep the old data and just add new entries.
Depending on whether I'm updating a high score (overwrite) or adding to a combat log (append), I'll switch between these modes. The pattern is always the same: fopen → NULL check → work → fclose.
📋 Practical Task
Exercise: Persistent Player Inventory Logger
Build a small utility that simulates saving a player's inventory to a file. Your program should do the following:
- Create a file named
inventory.txt. - Use the append mode (
"a") so that every time you run the program, the new items are added to the list rather than replacing the old ones. - Ask the user to input a single item name (a string) and the quantity of that item (an integer).
- Write that item and quantity to the file in a readable format (e.g., "Health Potion: 5").
- Ensure you check if the file opened successfully before writing and remember to close the file properly.
There are no comments for now.