2013-05-04 6 views
2

Я пытаюсь подсчитать количество элементов, прочитанных std::cin с помощью std::distance для аргумента конструктора вектора заранее, например, так:Расстояние между istream_iterators

// Gives correct amount, but now can't use to put into vector 
int size = std::distance(std::istream_iterator<std::string>(std::cin), 
     std::istream_iterator<std::string>()); 

std::vector v(size); 

// Already read from stream 
std::copy(...); 

Очевидно, что я могу закончить это в один шаг с std::copy, но для этого потребуется установка размера заранее. Однако мой вопрос касается не векторов, а порядка получения произвольного ввода с использованием std::istream_iterator без влияния на поток. Есть идеи?

+1

* «Очевидно, что я могу завершить это за один шаг с помощью std :: copy, но для этого потребуется установка размера заранее» * Да и нет, соответственно. Вы знаете о 'back_insert_iterator'? – jrok

+0

Даже если я согласен с преторианским ответом, это очень странное поведение с размером == 0. Как указано в этом документе [http://www.oopweb.com/CPP/Documents/STL/Volume/prw421. htm). Для входных итераторов r и s, r == s не подразумевает ++ r == ++ s: –

ответ

5

std::istream_iterator - InputIterator, что означает, что он поддерживает только один проход в диапазоне, который вы итерируете. Невозможно определить размер, а затем вернуться к началу, чтобы прочитать данные.

Вы можете прочитать из std::cin (или любого другого входного потока) с использованием std::copy, не зная размер заранее, просто использовать std::back_inserter добавлять данные считываются в vector.

std::vector v; 
std::copy(std::istream_iterator<std::string>(std::cin), 
      std::istream_iterator<std::string>(), 
      std::back_inserter(v)); 
+0

Ну, с поисковыми потоками вы можете 'seekg' до 0 и снова итерации. Я не говорю, что это хорошая идея ... – jrok

+0

@jrok Да, конечно. Я имел в виду, что нет способа сделать тот же самый итератор * ходить назад *. – Praetorian

Смежные вопросы