17

The C++ code below does int to string and a string to int conversions. Then, it repeats these steps again. The stringstream to int line stream1 >> i3; is breaking the code. What am I missing here?

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
 int i1 = 101;
 int i2 = 202;
 int i3 = 0;
 string s1 = "";
 string s2 = "";
 stringstream stream1;

 for (int i=0;i<2;i++)
 {

   //int to string
   stream1.str("");
   cout << "i1 " << i1 << endl;
   stream1 << i1;
   s1 = stream1.str();
   cout << "s1 " << s1 << endl;

   //int to string
   cout << "i2 " << i2 << endl;
   stream1.str("");
   stream1 << i2;
   s2 = stream1.str();
   cout << "s2 " << s2 << endl;

   //string to int
   stream1.str("");
   stream1.str(s2);
   stream1 >> i3;
   //line above causes s1 and s2 to get messed up during 2nd time in for loop
   cout << "i3-- " << i3 << endl;

  }
  return 0;
 }
Michael
  • 3,093
  • 7
  • 39
  • 83
user584583
  • 1,242
  • 4
  • 18
  • 35
  • Shouldn't you flip the `>>` to a `<<`?what output are you trying to get, I am not sure I follow. – Jordan Mar 29 '11 at 17:52
  • Abhay, your codepad link output is just like what I get. s1 and s2 should not be empty. If you comment out the stream1 >> i3 line you will see that s1 and s2 are 101 and 202 – user584583 Mar 29 '11 at 18:02
  • @user584583: Sorry. yes, that should not be empty. – Abhay Mar 29 '11 at 18:05

4 Answers4

19

I tested your code and could reproduce the problem. I solved it inserting a .clear() before .str("")

Have a look here: How to reuse an ostringstream?

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
 int i1 = 101;
 int i2 = 202;
 int i3 = 0;
 string s1 = "";
 string s2 = "";
 stringstream stream1;

 for (int i=0;i<2;i++)
 {

   //int to string
   stream1.clear();
   stream1.str("");
   cout << "i1 " << i1 << endl;
   stream1 << i1;
   s1 = stream1.str();
   cout << "s1 " << s1 << endl;

   //int to string
   cout << "i2 " << i2 << endl;
   stream1.clear();
   stream1.str("");
   stream1 << i2;
   s2 = stream1.str();
   cout << "s2 " << s2 << endl;

   //string to int
   stream1.clear();
   stream1.str("");
   stream1.str(s2);
   stream1 >> i3;
   //line above causes s1 and s2 to get messed up during 2nd time in for loop
   cout << "i3-- " << i3 << endl;

  }
  return 0;
 }
Community
  • 1
  • 1
Javi R
  • 2,320
  • 1
  • 17
  • 21
16

The problem is that the stream's EOF flag is being set while extracting the integer (i.e. stream1.eof() returns true), but you never clear it. Inserting a call to stream1.clear() after extraction fixes your issue.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
4

After reading i3 from the stream, the eof bit of the stream gets set. This is because reading an integer from the stream makes the stream read until either it reads a nondigit character or it runs out of characters to read. When the latter that happens, the eof bit is set.

For example, I can change this line,

stream1.str(s2);

to this,

stream1.str(s2 + " ");

so when stream1 >> i3; is executed, it will encounter a nondigit character (' '), stop reading and not set the eof bit.

You have to unset the eof bit by .clear or some other method before attempting to read from it.

tiftik
  • 978
  • 5
  • 10
1

I'm a C guy most of the day, so I would simply use atoi() do to the conversion:

#include <stdlib.h> // header for atoi()

//stream1 >> i3;  // replace this for the line below
i3 = atoi(stream1.str().c_str());

cout << "i3-- " << i3 << endl;

What I'm doing is retrieving a std::string from the stringstream, and from that, getting a const char* to be used as argument for atoi(), which converts a C string to an integer.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • This doesn't actually answer the question. – Cubbi Mar 29 '11 at 17:53
  • This is not quite correct. If you get data out from the stringstream into a string `s3` rather than the int `i3`, the same problem occurs. `stringstream` basically has to be reset with `clear()` after data is extracted from it -- regardless of any conversion of the data you extract. – michel-slm Mar 29 '11 at 18:03
  • 2
    I do this all the time without needing to call `clear()`. The call to `stream1.str()` gets information out of the stream without changing the status flags on the stream ( http://www.cplusplus.com/reference/iostream/stringstream/str/ ). – Max Lybbert Mar 29 '11 at 18:11
  • Well I suppose I could paste the entire source code of the application so you guys can test it, but since the code only has 2 changes on the original source code, I think it's not really necessary. Rest assured that this method was tested and works. – karlphillip Mar 29 '11 at 18:18
  • C++ guys don't like C answers.. is that enough reason for the downvotes? – karlphillip Mar 29 '11 at 18:25
  • http://stackoverflow.com/questions/8871711/atoi-how-to-identify-the-difference-between-zero-and-error – nvd Feb 24 '16 at 17:19
  • The downvotes are because while it "fixes" the problem. It doesn't explain why/how what the problem even was in the first place. So while it might fix the immediate issue, it's not very helpful for learning. – Rick Jun 09 '21 at 01:22