File I/O & Exception Handling
I. In-Class Exercises
Programming Exercises
II. Knowledge Summary
✨ File Redirection
File redirection refers to changing a program's console input/output to file input/output. Through file redirection, a program can read data from files and write results to files without modifying the cin and cout statements in the program.
✨ C++ File Input/Output
Using C++ style file operations requires including the <fstream> header and using the std namespace.
#include <fstream>
using namespace std;File Input
Use ifstream to create a reader variable, open a file with the open method, and close the file with close after reading.
1ifstream cin; // create a reader variable
2cin.open("in.txt"); // open the file
3if (!cin.is_open()) {
4 cout << "can't find file" << endl;
5}
6int number;
7cin >> number; // read data
8cin.close(); // close the fileFile Output
Use ofstream to create a writer variable and open the output file. If the file does not exist, it will be created automatically.
ofstream cout("out.txt"); // create a writer variable and open the output file
cout << "hello" << endl; // write data
cout.close(); // close the fileFile Read/Write
fstream supports simultaneous file reading and writing, with two modes available: append mode and truncate mode.
Append mode adds content to the end of the file:
fstream file("in.txt", ios::in | ios::out | ios::app);
int number;
file >> number;
file << "output";
file.close();Truncate mode clears the file content before writing:
fstream file("in.txt", ios::in | ios::out | ios::trunc);
int number;
file >> number;
file << "output";
file.close();✨ C-Style File Input/Output
Using C-style file redirection does not require any special header files. The freopen function can redirect standard input/output to files.
freopen("in.txt","r", stdin);
freopen("out.txt","w", stdout);The advantage of this approach is concise code. After redirection, all cin/scanf and cout/printf in the program will automatically read from and write to files. This is commonly used in competitive programming.
✨ Exception Handling
Exception Concepts
A program exception is a non-compilation error in a program, which may be system-defined or programmer-defined. Exception handling allows a program to continue running normally after an error occurs, improving the program's robustness.
Exception Handling Structure
Exception handling consists of three key components:
- throw: When an exceptional condition is detected, the program uses the
throwkeyword to throw an exception - try: The
tryblock surrounds code that may throw exceptions and specifies one or morecatchblocks to handle possible exceptions - catch: After an exception is thrown, the program captures and handles the exception in a
catchblock
The basic structure of try-catch is as follows:
1try {
2 // code that may throw an exception
3} catch (exception &error) {
4 // handle a specific type of exception
5} catch (...) {
6 // handle all other types of exceptions
7}The throw can be used directly within the try block or within a function called from the try block.
Sample Code
Below is an example of throwing exceptions directly within a try block:
1#include <iostream>
2#include <stdexcept>
3using namespace std;
4
5int main() {
6 int a, b;
7 cin >> a >> b;
8 try {
9 if (b == 0) {
10 throw runtime_error("divide zero");
11 }
12 if (a < b) {
13 throw invalid_argument("a < b");
14 }
15 if (a > 100 || b > 100) {
16 throw invalid_argument("out of range");
17 }
18 int result = a / b;
19 cout << a << " / " << b << " = " << result << endl;
20 } catch (runtime_error &error) {
21 cout << error.what() << endl;
22 } catch (invalid_argument &error) {
23 cout << error.what() << endl;
24 } catch (...) {
25 cout << "an unknow error" << endl;
26 }
27 return 0;
28}Below is an example of throwing exceptions inside a function and calling that function from a try block:
1#include <iostream>
2#include <stdexcept>
3using namespace std;
4
5int divide(int a, int b) {
6 if (b == 0) {
7 throw runtime_error("divide zero");
8 }
9 if (a < b) {
10 throw invalid_argument("a < b");
11 }
12 if (a > 100 || b > 100) {
13 throw invalid_argument("out of range");
14 }
15 int result = a / b;
16 return result;
17}
18
19int main() {
20 int a, b;
21 cin >> a >> b;
22 try {
23 int result = divide(a, b);
24 cout << a << " / " << b << " = " << result << endl;
25 } catch (runtime_error &error) {
26 cout << error.what() << endl;
27 } catch (invalid_argument &error) {
28 cout << error.what() << endl;
29 } catch (...) {
30 cout << "an unknow error" << endl;
31 }
32 return 0;
33}Exception Handling with File Operations
Exception handling is often combined with file operations to handle situations like file open failures:
1#include <iostream>
2#include <fstream>
3#include <stdexcept>
4using namespace std;
5
6int main() {
7 try {
8 ifstream fin("in.txt");
9 if (!fin.is_open()) {
10 throw runtime_error("no file");
11 }
12 } catch (runtime_error &e) {
13 cout << e.what() << endl;
14 }
15 return 0;
16}✨ Execution Examples for File I/O
The following examples demonstrate the complete workflow of file I/O and exception handling.
Example 1: Complete C++ Style File I/O Workflow
Assume the file in.txt contains:
3
10 20 30The program needs to read data from the file, compute the sum, and output to out.txt:
1#include <fstream>
2using namespace std;
3
4int main() {
5 // Step 1: Open the input file
6 ifstream fin("in.txt");
7
8 // Step 2: Read data
9 int n;
10 fin >> n; // read n = 3
11 int sum = 0;
12 for (int i = 0; i < n; ++i) {
13 int x;
14 fin >> x; // read 10, 20, 30 in sequence
15 sum += x;
16 }
17 fin.close(); // Step 3: Close the input file
18
19 // Step 4: Open the output file and write the result
20 ofstream fout("out.txt");
21 fout << "sum = " << sum << endl; // write "sum = 60"
22 fout.close(); // Step 5: Close the output file
23
24 return 0;
25}1Execution flow:
21. Open in.txt -> success
32. Read n=3
43. Loop read: x=10, sum=10 -> x=20, sum=30 -> x=30, sum=60
54. Close in.txt
65. Open out.txt (created automatically if it doesn't exist)
76. Write "sum = 60"
87. Close out.txt
9
10Final content of out.txt:
11sum = 60Example 2: Complete C-Style freopen Redirection Workflow
1#include <cstdio>
2using namespace std;
3
4int main() {
5 freopen("in.txt", "r", stdin); // redirect standard input to in.txt
6 freopen("out.txt", "w", stdout); // redirect standard output to out.txt
7
8 int a, b;
9 scanf("%d%d", &a, &b); // actually reads from in.txt
10 printf("%d\n", a + b); // actually writes to out.txt
11
12 return 0;
13}Execution flow:
1. freopen redirects stdin to in.txt -> all subsequent scanf/cin reads from in.txt
2. freopen redirects stdout to out.txt -> all subsequent printf/cout writes to out.txt
3. The I/O code in the program needs no modification, works exactly like console I/OCommon practice in competitions: Many competition problems require file I/O. Using
freopenonly requires adding two lines at the beginning of the program, with no changes to the rest of the code, which is very convenient.
Example 3: Exception Handling Execution Flow
1int a = 10, b = 0;
2try {
3 if (b == 0) {
4 throw runtime_error("divide zero"); // throw an exception
5 }
6 cout << a / b << endl; // this line will not execute
7} catch (runtime_error &error) {
8 cout << error.what() << endl; // catch and handle the exception
9}
10cout << "program continues" << endl; // program continues normally after exception handling1Execution flow:
21. Enter the try block
32. Check b == 0 -> condition is true
43. throw raises a runtime_error exception -> immediately exits the try block
54. The a / b line is skipped (will not execute)
65. Enter the matching catch block, output "divide zero"
76. After the catch block finishes, the program continues running normally
87. Output "program continues"Key understanding: After
throw, the remaining code in the try block will not execute. The program jumps directly to the matching catch block. After exception handling, the program continues from the code after the catch block.
✨ Problem-Solving Steps for File I/O
Steps for solving file I/O problems:
- Determine the I/O method: Decide whether the problem requires C++ style (ifstream/ofstream) or C style (freopen)
- Open the file: Choose the appropriate opening method
- Check if the file opened successfully: Use
is_open()or exception handling to determine if the file exists - Read/write data: After opening the file, the read/write syntax is essentially the same as console I/O
- Close the file: Always close the file after operations are complete
Steps for solving exception handling problems:
- Identify operations that might fail: Such as division by zero, file not found, array out of bounds, etc.
- Wrap potentially failing code with try
- Use throw at points where errors might occur
- Use catch to capture and handle exceptions: Multiple catch blocks can handle different types of exceptions
- Use
catch(...)as a fallback: Catches all exceptions not handled by previous catch blocks
✨ Common Mistakes with File I/O
- Forgetting to close files: Always call
close()after opening a file; otherwise data may not be fully written (buffer not flushed) - Incorrect file path: Programs look for files in the executable's directory by default. If the file is elsewhere, use the full path
- Forgetting about redirection after freopen: After using
freopen,cin/couthave been redirected to files. If you want to output debug information to the console, usecerr - Improper catch block ordering: Multiple catch blocks are matched from top to bottom. If
catch(...)is placed first, subsequent specific-type catch blocks will never execute - Writing code after throw that needs to execute: Code after
throwin the try block will not execute. Cleanup code should be placed in the catch block or after the try-catch - Naming ifstream variable the same as cin: The examples use
ifstream cin;for demonstration convenience. In actual programming, use a different variable name (such asfin) to avoid confusion with the standard inputcin
III. Homework
Knowledge Quiz
- File I/O and Exception Handling - Quiz## Programming Exercises