Чтобы замаскировать ifstream
(или, фактически, любой входной поток) в форме, которая действует как итератор, вы хотите использовать шаблонный класс istream_iterator
или istreambuf_iterator
. Первый полезен для файлов, где форматирование имеет значение. Например, файл, полный целых чисел, разделенных пробелами, может быть считан в конструктор диапазона итератора вектора следующим образом:
#include <fstream>
#include <vector>
#include <iterator> // needed for istream_iterator
using namespace std;
int main(int argc, char** argv)
{
ifstream infile("my-file.txt");
// It isn't customary to declare these as standalone variables,
// but see below for why it's necessary when working with
// initializing containers.
istream_iterator<int> infile_begin(infile);
istream_iterator<int> infile_end;
vector<int> my_ints(infile_begin, infile_end);
// You can also do stuff with the istream_iterator objects directly:
// Careful! If you run this program as is, this won't work because we
// used up the input stream already with the vector.
int total = 0;
while (infile_begin != infile_end) {
total += *infile_begin;
++infile_begin;
}
return 0;
}
istreambuf_iterator
используется для чтения файлов по одному символу за раз, независимо от форматирования ввода. То есть он вернет вам все символы, включая пробелы, символы новой строки и так далее. В зависимости от вашего приложения это может быть более подходящим.
Примечание: Скотт Мейерс объясняет в Effective STL , почему отдельные объявления переменных для istream_iterator
необходимы выше. Обычно вы делаете что-то вроде этого:
ifstream infile("my-file.txt");
vector<int> my_ints(istream_iterator<int>(infile), istream_iterator<int>());
Однако C ++ фактически анализирует вторую строку невероятно странным образом. Он видит это как объявление функции с именем my_ints
, которая принимает два параметра и возвращает vector<int>
. Первый параметр имеет тип istream_iterator<int>
и называется infile
(паратезы игнорируются). Второй параметр - это указатель на функцию без имени, который принимает нулевые аргументы (из-за паразитов) и возвращает объект типа istream_iterator<int>
.
Довольно круто, но и довольно обидно, если вы не следите за этим.
EDIT
Вот пример использования istreambuf_iterator
для чтения в файле 64-разрядных чисел, расположенных в сквозном порядке:
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char** argv)
{
ifstream input("my-file.txt");
istreambuf_iterator<char> input_begin(input);
istreambuf_iterator<char> input_end;
// Fill a char vector with input file's contents:
vector<char> char_input(input_begin, input_end);
input.close();
// Convert it to an array of unsigned long with a cast:
unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]);
size_t num_long_elements = char_input.size() * sizeof(char) / sizeof(unsigned long);
// Put that information into a vector:
vector<unsigned long> long_input(converted, converted + num_long_elements);
return 0;
}
Мне лично скорее не нравится это решение (использование reinterpret_cast
, отображение массива char_input
), но я недостаточно знаком с istreambuf_iterator
, чтобы удобно использовать один шаблонизированный над 64-битными символами, что сделать это намного проще.