如何用范围for循环从ifstream读取行?是否存在getline_range?
问题描述
我原本用这段代码从文件中逐行解析:
ifstream input(filename); for (string line; getline(input, line); /**/) do_something_with(line); ...
想知道有没有优雅的方式(比如借助Boost工具)把它改写成简洁的范围for循环形式,比如类似下面示例里的getline_range工具:
for (const auto& line : getline_range(ifstream(filename))) do_something_with(line); ...
解决方案
1. 用Boost.Range实现
Boost.Range提供了直接适配getline的工具,能满足你的需求。需要引入<boost/range/adaptor/stream.hpp>和<boost/range/iterator_range.hpp>头文件,用法如下:
#include <boost/range/adaptor/stream.hpp> #include <fstream> #include <string> // 简洁写法 for (const auto& line : boost::adaptors::stream_lines(std::ifstream(filename))) { do_something_with(line); }
注意:项目需要链接Boost.Range库才能正常编译运行。
2. C++20标准库原生实现(无需第三方库)
如果你的编译器支持C++20,也可以自己实现一个极简版的getline_range,完全贴合需求:
#include <fstream> #include <string> struct getline_range { std::ifstream stream; explicit getline_range(const std::string& filename) : stream(filename) {} struct iterator { std::ifstream* stream_ptr; std::string current_line; iterator(std::ifstream* ptr) : stream_ptr(ptr) { if (stream_ptr && *stream_ptr) std::getline(*stream_ptr, current_line); } bool operator!=(const iterator& other) const { return stream_ptr != other.stream_ptr || *stream_ptr; } iterator& operator++() { std::getline(*stream_ptr, current_line); return *this; } const std::string& operator*() const { return current_line; } }; iterator begin() { return iterator(&stream); } iterator end() { return iterator(nullptr); } }; // 使用方式和你设想的完全一致 for (const auto& line : getline_range(filename)) { do_something_with(line); }
这个自定义范围类会在构造时打开文件,迭代器每次递增时自动读取下一行,直到文件结束。
3. 用range-v3库实现
如果可以引入range-v3这个现代化范围库,写法会更简洁直观:
#include <range/v3/view/getlines.hpp> #include <fstream> // 使用示例 for (const auto& line : ranges::views::getlines(std::ifstream(filename))) { do_something_with(line); }
ranges::views::getlines完全匹配你想要的getline_range功能,语法非常简洁。
内容的提问来源于stack exchange,提问作者Darko Veberic
相关产品推荐
相关产品推荐

