最稳妥方法是用std::vector逐行读取再倒序输出,避免直接反转字符串破坏行内顺序;需注意Windows换行符\r残留、EOF处理及空行保留。

用 std::vector<:string></:string> 存行再倒序遍历最稳妥
直接反转文件或字符串的“行序”,本质是把每行内容读入容器,然后逆向输出。不能靠翻转原始字符串(比如用 std::reverse 作用于整个 std::string),否则会破坏每行内部字符顺序,只应反转行与行之间的顺序。
常见错误是试图用 std::getline 读完后立刻用 std::reverse 处理一个 std::string,结果所有换行符和文字全混成一团,行边界丢失。
- 用
std::vector<:string></:string>逐行接收,天然保留每行原始内容(不含\n) - 读完后用反向迭代器
rbegin()/rend()输出,或用下标从size()-1往 0 遍历 - 注意:如果输入含空行,
std::getline仍会存入空std::string,这是符合预期的行为
std::vector<std::string> lines;
std::string line;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
for (auto it = lines.rbegin(); it != lines.rend(); ++it) {
std::cout << *it << '\n';
}
从文件读取时注意 std::getline 的 EOF 行为
从文件读取时,最后一行没换行符(Unix 常见),std::getline 仍能成功读入该行并返回 true;但如果文件为空,第一次调用就失败,lines 为空,后续反向遍历不执行,没问题。
容易踩的坑是写成 while (!ifs.eof()) { std::getline(ifs, line); ... } —— 这会导致最后一行被重复处理一次,因为 eof() 只在读失败后才置位。
立即学习“C++免费学习笔记(深入)”;
- 永远用
while (std::getline(...))作为循环条件 - 不要依赖
eof()或fail()判断是否继续读 - 如果需区分“读到空行”和“读失败”,检查
line.empty()和流状态分开判断
内存受限时可用双栈实现 O(1) 额外空间?不现实
有人想避免存储全部行,用两个栈模拟:先全压入栈 A,再逐个弹出压入栈 B,最后弹出 B 输出。这仍是 O(n) 空间(两倍字符串存储),且无实际优势。
真正节省内存的做法不存在——你必须至少暂存所有行首地址或完整内容,才能知道“最后一行是什么”。除非数据源支持随机访问(如 mmap 文件 + 扫描换行符偏移),但 C++ 标准库无现成封装,复杂度远超需求。
- 别为了“省空间”手写栈或链表;
std::vector的连续内存和缓存友好性通常更优 - 若单行极长(MB 级)、总行数极少,可考虑
std::list<std::string>避免 vector 的可能扩容拷贝,但差异微乎其微 - 没有“边读边倒着输出”的标准方法;行序反转必有延迟,这是问题本质决定的
处理 Windows 换行符 \r\n 时要留意
std::getline 默认以 \n 为分隔符,并自动丢弃它;遇到 \r\n 时,\r 会留在读出的 std::string 末尾。这导致输出时可能显示异常(比如控制台回车未生效、文本错位)。
- 若输入可能来自 Windows,读入后检查
line.back() == '\r'并pop_back() - 更健壮的方式:用
line.erase(std::find(line.begin(), line.end(), '\r'), line.end());清除所有\r - 不需要手动处理
\n,因为std::getline已剥离
这个细节常被忽略,尤其当程序在 Linux 编译但在 Windows 下读取文件时,第一眼看不出问题,直到某天输出发给别人打开乱码。


















