2

I emptied a stringstream, then I tried to fill it again without any success. II don't understand why. Here is my code:

#include <string>
#include <iostream>
#include <sstream>

using namespace std;

int main(int argc, char* argv[] ) {

 stringstream ss1, ss2;
 ss1 << "0 1 2 3 40 5 6 76 8 9"; // Stream is filled with one string of chars
 vector <int> V;
 string st;
 int number;


 while(!ss1.eof() ) {
  ss1 >> number;  // Next int found in ss1 is passed to number
  V.push_back(number);
  ss2 << number << " "; // ss2 is filled with number + space in each iteration.  
 }   // Basically here, the content of ss1 has been passed to ss2, leaving ss1 empty.

 ss1 << "helloooo";
 getline(ss1, st);
 cout << st << endl; // <--- Here, st appears to be empty... Why ?

 return 0;
}
Alexandre Toqué
  • 163
  • 1
  • 3
  • 11
  • `while (!eof())` is really buggy. Use `while (ss1 >> number)`. – chris Aug 25 '13 at 17:45
  • It works your way too, but why would eof() be buggy? Anyway my ss1 stringstream still can't take another string :( How comes? – Alexandre Toqué Aug 25 '13 at 17:54
  • The problem with `eof()` is that it may never be reached, e.g., when you add a non-digit into your string: the stream will go into failure mode (i.e., `std::ios_base::failbit` gets set) but unless you get over that, it won't ever reach EOF (i.e., `std::ios_base::eofbit` will never be set). More importantly, you need to check your stream **after** you tried to read because the stream doesn't know what you are going to attempt. – Dietmar Kühl Aug 25 '13 at 17:57
  • [This question](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) asks exactly that. – chris Aug 25 '13 at 17:59

3 Answers3

3

First off, you should check if reading from the stream is successful by converting the stream to a Boolean value after you tried to read from it, e.g.:

while (ss1 >> number) {
    ...
}

Not testing after the input tends to result in processing the last input twice. Now, once this loop terminates, ss1 is in failure state, i.e., it has std::ios_base::failbit set. At this point the stream will refuse to do anything else until the bit is cleared. You can use clear() to reset the stream state:

ss1.clear();

After that the stream should be in good shape again.

Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356
0

Since you hit eof, the stream is in an error state. You have to reset it before you can use it again. In your case, I would drop the reset, and just use a fresh stringstream object.

Oh, and after ss1 >> number you should check the state of ss1 before using number. eof() doesn't return true before the last read failed

0

Although you'll still need to clear() the stream to write to it after you finish reading, you might consider using istream_iterators to read the data from the file:

stringstream ss1("0 1 2 3 40 5 6 76 8 9");

// initialize V from ss1
vector <int> V{std::istream_iterator<int>(ss1), std::istream_iterator<int>()};

// write values from V to ss2
std::copy(V.begin(), v.end(), std::ostream_iterator<int>(ss2));

ss1.clear();
ss1 << "helloooooo";
Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035