C++ 进阶 — 第 7 课
if (!in),打不开立刻退。while (in >> x) 或 getline。cout 把数据输出到屏幕;ofstream 把数据输出到文件。用法几乎一样:
#include <fstream>
using namespace std;
int main() {
ofstream out("scores.txt"); // 打开文件准备写入(不存在会自动创建)
out << 95 << " " << 87 << endl; // 和 cout 一模一样的写法
out << "Alice" << endl;
out.close(); // 关闭文件(可选,程序结束也会自动关)
return 0;
}
看这段代码,和屏幕输出唯一的区别是第一行:把 cout 换成了一个绑定到文件的 out。后面的 <<、endl 一个字都没变。
output(输出)→ 写文件;input(输入)→ 读文件。
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream in("scores.txt"); // 打开文件准备读取
int a, b;
string name;
in >> a >> b >> name; // 和 cin 一样,按空格/换行分隔
cout << a << " " << b << " " << name;
in.close();
return 0;
}
in >> a >> b >> name 的切分规则和 cin 完全一致:空格、换行都算分隔符,一个 >> 读一个。所以写文件时用什么分隔,读的时候心里要有数。
in 是「空」的。养成检查习惯:if (!in) { cerr << "打不开文件" << endl; return 1; }
ifstream in("data.txt");
string line;
while (getline(in, line)) { // 每次读一行,读到文件结束自动停止
cout << line << endl;
}
while (getline(in, line)) 和之前学的 while (cin >> x) 是同一个套路:「读到没有为止」。>> 遇空格就停,getline 一行读完 —— 行里有空格就用它。
ifstream in("nums.txt");
int x, sum = 0;
while (in >> x) { // 读到文件末尾时 in >> x 返回 false,循环结束
sum += x;
}
cout << sum << endl;
不用先数文件里有几个数:条件里直接 in >> x,读到末尾它会失败,循环自然退出。这是「数据量未知」时的标准写法。
默认的 ofstream 打开已存在的文件会直接清空重写。想保留旧内容追加,用 fstream + 打开模式:
#include <fstream>
using namespace std;
int main() {
fstream f("log.txt", ios::out | ios::app); // 追加模式:不清空旧内容
f << "hello" << endl;
return 0;
}
| 模式 | 作用 |
|---|---|
ios::out | 写文件(默认会覆盖旧内容) |
ios::in | 读文件 |
ios::app | 追加(append),不清空 |
ios::trunc | 打开时清空文件再写 |
多个模式用 | 拼起来,读代码时从左往右念就行:ios::out | ios::app = 「要写,而且往末尾接」。
假设 scores.txt 每行是一个名字 + 一个分数:
Alice 95
Bob 87
Cindy 92
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream in("scores.txt");
ofstream out("avg.txt");
if (!in) { // 打不开就退出
cerr << "打不开 scores.txt" << endl;
return 1;
}
string name;
int score, sum = 0, cnt = 0;
while (in >> name >> score) { // 每次读两个数据
sum += score;
cnt++;
}
out << "人数: " << cnt << endl;
out << "平均分: " << (cnt ? sum / cnt : 0) << endl;
cout << "已写入 avg.txt" << endl;
return 0;
}
这段是前面所有片段的组合:打开两个流 → 检查打不开 → 循环读 → 循环外统一写。cnt ? sum / cnt : 0 是防除零:文件是空的时候 cnt 为 0,直接除会崩。
| 方向 | 屏幕 | 文件 |
|---|---|---|
| 输出(写) | cout << x | ofstream out("f.txt"); out << x; |
| 输入(读) | cin >> x | ifstream in("f.txt"); in >> x; |
记住这张表,就不用背任何新语法:文件流只是把 cout/cin 换了个去向。
#include <fstream> 没写,编译器会说 ofstream 未声明 —— 看到这个报错先翻文件头。if (!in) 只要一行。ios::out | ios::app。while (in >> x) 已经处理了「读到末尾」,条件里再加 in.eof() 之类的判断容易多读一次。grades.txt:每行一个名字和一个分数best.txt:名字 分数while (in >> name >> score) 这个套路。grades.txt 和程序跑起来的目录是不是同一个。if (!in) 加了吗?没加的话,先加上再看结果,别猜。while (in >> name >> score),两个变量都要读,少一个就会错位。best.txt 之后真的打开看一眼 —— 别只信屏幕输出。grades.txt 内容、代码、best.txt 一起贴过来。if (!in),防止打不开ios::app 追加,默认是清空重写