1

I'm new to C++ and I'm confused about using iterators with ifstream. In this following code I have an ifstream variable called dataFile.

In the code I first iterate through the file once to count how many characters it has (is there a more efficient way to do this?). Then I create a matrix of that size, and iterate through again to fill the matrix.

The problem is that the iterator refuses to iterate the second time around, and will not do anything. I tried resetting the ifstream from the beginning by using dataFile.clear(), but this didn't work, probably because I have some deep misunderstanding about iterators. Could someone help me please?

typedef istreambuf_iterator<char> dataIterator;
for (dataIterator counter(dataFile), end; counter != end; ++counter, ++numCodons) {} // Finds file size in characters.
MatrixXd YMatrix = MatrixXd::Constant(3, numCodons, 0);
dataFile.clear(); // Resets the ifstream to be used again.
for (dataIterator counter(dataFile), end; counter != end; ++counter) {...}
user1634426
  • 563
  • 2
  • 5
  • 12
  • When you iterate the first time, and when the loop ends, `counter` will equal `end`. This means that the file stream has read all the characters. When you try to iterate again, the file stream is already at the end of the stream and can no longer go any further. – David G Mar 10 '14 at 01:47
  • To answer your efficiency question, if you know the file is just a raw character file, and you know it will ONLY contain characters you care about (including **newlines**), you could `stat` it and use the file size as the character count. But that only works in very controlled situations. To avoid having to iterate twice you could read all of the characters into a `LinkedList`, then reshape the list to the format you want. – aruisdante Mar 10 '14 at 01:53
  • Thanks guys. I think I probably could use the stat method, since the files are simply long strings of characters. – user1634426 Mar 10 '14 at 02:02
  • @aruisdante: Using a LinkedList is bad advice; there are ver few cases where that's the best datastructure. Also in this case, it 's better to just use a `std::vector<>` or `std::string`. – MSalters Mar 10 '14 at 10:43

1 Answers1

3

istreambuf_iterator is an input iterator which once has been incremented, all copies of its previous value may be invalidated, not a forward iterator which guarantees validity when used in multipass algorithms. More about the category of iterators, see here.

jfly
  • 7,715
  • 3
  • 35
  • 65
  • Thanks for the quick response! Do you know if there is a corresponding forward iterator I can use for ifstream, or if I could copy the stream itself to use a second time? – user1634426 Mar 10 '14 at 02:00
  • take a look at this [post](http://stackoverflow.com/questions/9026734/bidirectional-iterator-over-file-ifstream). – jfly Mar 10 '14 at 02:02