C++
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C++
-
Section 4: Memory Management
-
Section 5: Templates and Generic Programming
-
Section 6: The Standard Template Library
-
Section 7: Modern C++ Features
-
Section 8: Error Handling
-
Section 9: Multithreading
-
Section 10: Operator Overloading and Type Conversion
-
Section 11: Advanced Topics
-
Section 12: Tooling and Build Systems
-
Section 13: Design Patterns in C++
-
Section 14: Interfacing with C and Systems Programming
-
Section 15: Networking and IPC Basics
-
Section 16: Graphics and Game Programming Basics
-
Section 17: The Boost Libraries
-
Section 18: Data Structures and Algorithms in C++
-
Section 19: Practical Projects
-
Section 20: More Concurrency Patterns
-
Section 21: More OOP and Design Practice
-
Section 22: File I/O and Streams
-
Section 23: More Standard Library
-
Section 24: Practice Exercises
-
Section 25: Interview and Algorithm Practice
-
Section 26: Compiler and Language Internals
-
Section 27: GUI and Application Frameworks Overview
-
Section 28: Testing and Quality Practices
-
Section 29: Numerics Library
-
Section 30: Concepts Library (C++20)
-
Section 31: Ranges Library (C++20) In Depth
-
Section 32: More Utility Library
196: Reading and Writing Files with fstream
Up until now, everything we've built disappears the moment you close the terminal. That's fine for learning syntax, but real software needs a memory. In C++, we handle this through the fstream library. It's basically the same logic as cin and cout, just redirected to a file on your hard drive instead of a screen or keyboard.
To show you how this works, let's build a simple High Score Tracker for a game. We want to save the player's name and their score to a file, and then load it back when the program starts up.
Saving the score with ofstream
First, we need ofstream (output file stream). Think of this as your "writer." I'll start by creating a function that takes a name and a score and dumps them into a file called highscore.txt.
#include <iostream>
#include <fstream>
#include <string>
void saveScore(const std::string& name, int score) {
std::ofstream outFile("highscore.txt");
if (outFile.is_open()) {
outFile << name << "\n";
outFile << score << "\n";
outFile.close();
} else {
std::cerr < "Error: Could not open file for writing!" < std::endl;
}
}
Notice I checked is_open(). Never assume the OS is going to let you write to a file; permissions issues or read-only directories can kill your program if you aren't careful.
The classic getline trap
Now we need to read that data back. I'll use ifstream (input file stream). When I first wrote this, I tried to use the extraction operator (>>) to read the name. It looked like this:
std::string name;
int score;
std::ifstream inFile("highscore.txt");
inFile >> name >> score; // This is where I messed up
Here is the problem: if the player entered "John Doe", inFile >> name only grabs "John". The extraction operator stops at the first whitespace it hits. "Doe" then stays in the buffer, and when the program tries to read the int score, it sees "Doe" and fails miserably because "Doe" isn't a number. I spent ten minutes staring at the screen before I realized I needed std::getline.
Here is the corrected version that handles full names correctly:
void loadScore() {
std::ifstream inFile("highscore.txt");
std::string name;
int score;
if (inFile.is_open()) {
std::getline(inFile, name); // Reads the whole line, including spaces
inFile >> score; // Now we can grab the integer
std::cout < "Loaded High Score: " < name < " with " < score < " points!" < std::endl;
inFile.close();
} else {
std::cout < "No high score file found. Start a new game!" < std::endl;
}
}
Putting the pieces together
To wrap this up, we just need a main function to trigger these. I'm using a simple flow: load the old score, ask for a new one, and save it. One thing to remember: std::ofstream` by default overwrites the file. If you wanted to keep a list of all top scores instead of just the best one, you'd need to open the file in "append mode" using std::ios::app.
int main() {
loadScore();
std::string playerName;
int playerScore;
std::cout < "Enter your name: ";
std::getline(std::cin, playerName);
std::cout < "Enter your score: ";
std::cin >> playerScore;
saveScore(playerName, playerScore);
std::cout < "Score saved successfully!" < std::endl;
return 0;
}
I usually prefer letting the fstream destructor handle the file closing (it happens automatically when the object goes out of scope), but calling .close() explicitly is a good habit. It makes it clear to anyone reading your code exactly where the file interaction ends.
📋 Practical Task
Build a Persistent Daily Journal Logger
Your task is to create a program that acts as a simple journal. Unlike the high score example which overwrites the file, this program must append new entries to the end of the file so that previous entries are preserved.
Requirements:
- The program should prompt the user for a date (e.g., "2023-10-27") and a short journal entry (a full sentence).
- Use
std::ofstream` with thestd::ios::appflag to ensure new entries don't delete old ones. - Save the data in the format:
[Date] Entry Text. - After saving, the program should read the entire file from the beginning and print all previous journal entries to the console to confirm the save worked.
- Ensure you use
std::getlineto handle the spaces in the journal entry.
There are no comments for now.