Могу ли я использовать istream_iterator <char>для копирования некоторого содержимого istream в std :: string? - PullRequest
4 голосов
/ 17 октября 2019

У меня есть istream, и мне нужно скопировать содержимое между двумя разделителями в std::string. Я могу найти разделители streampos, но при попытке использовать istream_iterator<char> для перебора части потока это не работает. Вот что я попробовал:

#include <iostream>
#include <sstream>
#include <iterator>


std::string copyToString( std::istream& is )
{
    is >> std::ws;

    auto someLength {10};

    std::istream_iterator<char> beg {is};

    is.seekg( someLength, std::ios::cur );

    //std::istream_iterator<char> end { is };
    std::istream_iterator<char> end { std::next(beg, someLength) };

    return std::string{ beg, end };
}




int main()
{
    std::stringstream ss;
    ss.str( "   { my string content  }" );

    std::cout << "\"" << copyToString( ss ) << "\"\n";

    return 0;
}

Я ожидал, что на выходе будет 10 символов, но это просто "{". Если я раскомментирую строку std::istream_iterator<char> end { is }; и закомментирую следующую, вывод будет просто "".

Чего мне не хватает? Разве я не могу использовать такие итераторы?

Я знаю, что мог бы создать char[] в качестве буфера, скопировать его в него и т. Д., Но это кажется гораздо менее простым.

1 Ответ

2 голосов
/ 17 октября 2019

std::istream_iterator является входным итератором . Входные итераторы являются однопроходными и становятся недействительными при увеличении их копий. Когда вы делаете std::next(beg, someLength), вы читаете someLength символов. Тогда beg становится недействительным.

Более того, std::istream_iterator не предназначено для подсчета. Он разработан для сравнения с созданным по умолчанию итератором из-за способа обработки ошибок потока. Если вы попытаетесь их подсчитать, то они будут иногда читать еще раз, в зависимости от того, как реализован алгоритм.

Если вы хотите прочитать n символов из входного потока, простоиспользуйте read. Если вы хотите пропустить пробелы, просто напишите цикл. Если вы хотите использовать std::istream_iterator непреднамеренным образом, ваш код будет непредсказуемым.

...