[原创](Modern C++)现代C++的关键性概念: 流迭代器std::istream_iterator的优秀用法
[作者]
常用网名: 猪头三
出生日期: 1981. XX. XX
企鹅交流: 643439947
个人网站: 80x86汇编小站
编程生涯: 2001年~至今[共24年]
职业生涯: 22年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测
[序言]
在现代C++编程中, std::istream_iterator是一个强大且实用的工具, 它以迭代器的方式从输入流(如 std::cin, 或文件流, 或者内存流等)中读取数据. 这种方法不仅简化了代码, 还能与标准模板库(STL)的算法无缝结合, 提升代码的可读性和效率.
[std::istream_iterator是什么?]
std::istream_iterator是C++标准库中的一个输入迭代器类模板, 用于从std::istream对象(如 std::cin、std::ifstream、内存流等)中读取数据. 它将流中的数据抽象为迭代器接口, 使得可以像操作容器元素一样处理流数据.
其模板参数通常包括:
数据类型: 指定要读取的目标类型(如 int、double、std::wstring 等).
字符类型: 指定流的字符类型(如 char 或 wchar_t).
例如:
std::istream_iterator<int, char> 从流中读取int类型数据.
std::istream_iterator<std::wstring, wchar_t>从宽字符流中读取std::wstring数据.
std::istream_iterator<double, wchar_t>从宽字符流中读取double数据.
[默认构造的std::istream_iterator被称为流末尾迭代器又是什么?]
默认构造的std::istream_iterator(即不传入参数的构造, 如 std::istream_iterator<int>{})被称为流末尾迭代器. 它不绑定任何流, 表示流的结束位置, 类似于容器中的end()迭代器. 在使用 std::istream_iterator时, 通常搭配一个绑定流的迭代器(指向流开始)和一个流末尾迭代器(表示流结束)来定义读取范围.
例如:
std::vector<std::wstring> wstr_Words{
std::istream_iterator<std::wstring, wchar_t>{wiss_span_StrInput}, // 流开始
std::istream_iterator<std::wstring, wchar_t>{} // 流末尾
};
// 这里的第二个参数std::istream_iterator<std::wstring, wchar_t>{}表示读取到流结束为止.
[std::istream_iterator迭代器默认如何处理空白符?]
默认情况下, std::istream_iterator使用重载的提取运算符(<<)读取数据, 而该运算符在进行格式化输入时会自动跳过空白符(如空格、制表符、换行符等). 因此, 当您流中读取字符串、数字等数据时, 不必担心空白符会干扰数据的提取, 系统会自动忽略这些分隔符.
[std::noskipws是什么?]
std::noskipws是一个流操纵符, 用于关闭输入流中自动跳过空白符的行为. 将std::noskipws应用于输入流后, 所有字符(包括空格、制表符和换行符)都将被当作有效数据读取. 这在需要逐字符处理或精确读取流内容时非常有用. 例如, 当需要保留输入格式或解析特殊格式数据时, std::noskipws就派上了用场.
[std::istreambuf_iterator是什么?]
std::istreambuf_iterator是另一种流迭代器, 与std::istream_iterator不同, 它直接从流的缓冲区读取字符, 不经过格式化输入操作. 由于不涉及格式转换和跳过空白符的机制, std::istreambuf_iterator通常在高效读取大块原始数据时表现更优. 此外, 该迭代器可以用来实现文件拷贝、字符串拼接等底层操作, 是处理底层I/O时的重要工具.
* 不受流状态(如 std::noskipws)影响.
* 属于单遍迭代器, 不支持多遍迭代或随机访问.
* 常用于快速读取原始字符序列, 例如文件复制.
[代码演示]
int main()
{
_setmode(_fileno(stdout), _O_WTEXT);
// 1: 演示流迭代器处理空白符
std::wstring_view wstr_Input{ L"aaa bbb ccc\r\nddd eee" };
std::wispanstream wiss_span_StrInput{ wstr_Input };
std::vector<std::wstring> wstr_Words{ std::istream_iterator<std::wstring, wchar_t>{wiss_span_StrInput},
std::istream_iterator<std::wstring, wchar_t>{} };
for (const auto& item_word : wstr_Words)
{
std::wcout << item_word << std::endl;
}
// 2: 演示流迭代可以自动支持字符型自动换转为其他类型
std::wstring_view wstr_Input_Double{ L"0.1 0.2 0.3 0.4" };
std::wispanstream wiss_span_DoubleInput{ wstr_Input_Double };
std::partial_sum(std::istream_iterator<double, wchar_t>(wiss_span_DoubleInput),
std::istream_iterator<double, wchar_t>(),
std::ostream_iterator<double, wchar_t>(std::wcout, L" "));
// 3: 演示流迭代支持标准算法
std::wstring_view wstr_Input_Int{ L"1 3 5 7 8 9 10" };
std::wispanstream wiss_span_IntInput{ wstr_Input_Int };
auto it_Found = std::find_if(std::istream_iterator<int, wchar_t>(wiss_span_IntInput),
std::istream_iterator<int, wchar_t>(),
[](auto param_Arg){ return param_Arg % 2 == 0; });
if (it_Found != std::istream_iterator<int, wchar_t>())
std::wcout << L"\n找到第一个可被2整除的数: " << *it_Found << ".\r\n";
std::cin.get();
return 0;
}
[代码作用]
这些代码展示了std::istream_iterator的核心功能:
1. 自动处理空白符: 方便从流中提取单词或数据.
2. 类型转换支持: 将字符流转为指定类型(如 double、int).
3. 与STL算法集成: 支持std::partial_sum、std::find_if等标准算法, 像操作容器一样处理流数据.
[总结]
std::istream_iterator是现代C++中一个简洁而强大的工具, 它将输入流抽象为迭代器, 简化了数据读取并与STL算法无缝衔接. 掌握std::istream_iterator可以编写更高效、可读性更强的代码.