Инициализация строки с парой итераторов - PullRequest
2 голосов
/ 09 ноября 2009

Я пытаюсь инициализировать строку с помощью итераторов, и что-то вроде этого работает:

ifstream fin("tmp.txt");  
istream_iterator<char> in_i(fin), eos; 
//here eos is 1 over the end  
string s(in_i, eos);

но это не так:

ifstream fin("tmp.txt");
istream_iterator<char> in_i(fin), eos(fin);
/* here eos is at this same position as in_i*/
//moving eos forward 
for (int i = 0; i < 20; ++i)
{
    ++eos; 
}
// trying to initialize string with 
// pair of iterators gives me "" 
// result  
string s(in_i, eos);

Спасибо.

Ответы [ 4 ]

2 голосов
/ 09 ноября 2009

Я не думаю, что вы можете продвинуть конечный итератор в подходящее положение: продвинуть итератор означает читать входные данные, также оба итератора ссылаются на один и тот же поток - поэтому продвижение одного итератора означает продвижение второго. Они оба в итоге ссылаются на одну и ту же позицию в потоке.

Если вы не захотите написать или найти адаптер итератора (boost?), Который выполняет операцию с n элементами, на которые ссылается какой-либо итератор, может быть невозможно инициализировать строку таким образом. Или вы читаете значение другими методами и позже устанавливаете значение строки.

1 голос
/ 09 ноября 2009

istream_iterator - очень ограниченный итератор, известный как итератор ввода.

См .: http://www.sgi.com/tech/stl/InputIterator.html

Но в основном для входных итераторов сделано очень мало гарантий.
Специально для вашего случая:

i == j не подразумевает ++ i == ++ j.

Итак, ваш первый пример - итератор, которому передается конец потока. Он действителен (пока он не увеличен) и сравним с другими итераторами, поэтому работает для чтения всего потока.

1 голос
/ 09 ноября 2009

istream_iterator вводится, поэтому ваш второй фрагмент кода неверен, вы не можете сделать это (второй проход). Пожалуйста, посмотрите здесь и обратите внимание на поддержку алгоритмов "одного прохода" (второй абзац под заголовком "описание"). Первый фрагмент не пытается выполнить 2 прохода.

Это объяснение в порядке? Кстати, ссылка SGI STL (откуда я разместил ссылку) несколько устарела, но очень полезна для некоторых быстрых ссылок (по моему мнению). Я бы порекомендовал его в закладки.

0 голосов
/ 09 ноября 2009

Из стандарта [24.5.1] / 1:

[...] Конструктор без аргументов istream_iterator () всегда создает конец входного итератора потока объект, который является единственным законным итератор, который будет использоваться для конца состояние. [...] Главная особенность итераторов istream заключается в том, что операторы ++ не сохраняют равенство, то есть i == j вовсе не гарантирует, что ++ i == ++ j. Каждый раз, когда используется ++, читается новое значение.

[24.5.1] / 3

Два итератора конца потока всегда равны Конец потока итератор не равен итератор без конца потока. Два итераторы без конца потока равны когда они построены из тот же поток

В первом абзаце говорится, что вы не можете использовать любые итераторы конца потока в качестве конечных условий, поэтому ваше первое использование правильное и ожидаемое. Третий абзац в этой главе гласит, что любые два итератора, не относящиеся к концу потока, в один и тот же поток гарантированно всегда будут равны. То есть второе использование является правильным с точки зрения языка и обеспечит результаты, которые вы получаете.

Последняя часть параграфа 1, где говорится, что i == j не подразумевает ++i == ++j, имеет дело с частным случаем одного последнего элемента, присутствующего в потоке. После приращения первого из итераторов (i или j) этот итератор использует данные. Продвижение другого итератора дойдет до конца потока, и поэтому два итератора будут различаться. Во всех остальных случаях (в потоке осталось более одного элемента данных), ++i == ++j.

Также обратите внимание, что предложение ++i == ++j выполняет две операции мутирования для одного и того же элемента (потока), и, следовательно, это не тот, который из двух итераторов получает первый / второй элемент данных в потоке.

...