Search code examples
c++vectoristream-iterator

Initializing a vector with istream_iterator before while loop, does this operation affect following loop?


When adding vector<string> vec(file_iter, eof); before the while loop, that loop will run only once. Why?

istream_iterator<string> file_iter(in), eof;
map<string, size_t> word_cout;
vector<string> vec(file_iter, eof);
while (file_iter != eof)
{
 auto ret = word_cout.insert(make_pair(*file_iter, 1));
 if (ret.second == false) ++ret.first->second;
 ++file_iter;
}


Solution

  • The construction here:

    vector<string> vec(file_iter, eof);
    

    passes a copy of the file_iter and eof iterators to the vector constructor, where it then abuses the former to load the vector with content. Whilst doing so the underlying stream in is continually read from until such time as a stream error or EOF is encountered. Once that happens, the stream is in error or eof state, the reads are done, and the vector is finished being populated.

    Then, back to your next line of code:

    while (file_iter != eof)
    

    Remember, that's still the original file_iter before a copy of it was used to run the stream to eof. The initial prime of that iterator is still intact, but as soon as you advance it (++file_iter) the stream is discovered to be at eof, the iterator is set as such, and now the while-condition will compare as false.

    If you want to load your vector and build the frequency map, use an iterator over the vector for the latter, or better still, a ranged-for loop:

    istream_iterator<string> file_iter(in), eof;
    map<string, size_t> word_cout;
    vector<string> vec(file_iter, eof);
    for (auto const& s : vec)
        ++word_count[s];
    

    Now vec contains every word in your file, and your map contains the frequencies of said-same.