2

Is it possible to stringstream like this? I am trying to read with ifstream and convert it.

string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;
stringstream into;
into << things;
into >> i1;
into >> i2;
into >> i3;
into >> i4;

I expect it to be :

i1 = 10
i2 = 11
i3 = 12
i4 = -10

is that correct?

Can the same stringstream variable be used multiple times?

When I tried, the first time was ok but everything else later on is just 0.

3
  • Is that not the result you are getting? Commented Feb 20, 2011 at 5:19
  • How about compiling that code and see for yourself ? Commented Feb 20, 2011 at 5:28
  • 3
    Because compilable code that produces a right result in one instance always means it's 100% correct, especially in C++... Commented Feb 20, 2011 at 5:31

5 Answers 5

6

That should definitely work. You can even mix types, as shown below:

string things = "10 Nawaz 87.87 A";
int i;
std::string s;
float f;
char c;

stringstream into;
into << things;
into >> i >> s >> f >> c; //all are different types!

cout << i <<"  "<< s <<"  "<< f <<"  "<< c;

Output:

10 Nawaz 87.87 A

Demo at ideone : http://www.ideone.com/eb0dR

Sign up to request clarification or add additional context in comments.

Comments

1

Does it work? The way I would do it is:

istringstream into(things);
into >> i1;

and so on. That would produce the output you posted.

Comments

1

What you posted works, along with Jeremiah Willcock's solution using istringstream instead. But consider using the scanf family of functions as well (for just a couple of ints it doesn't make much of a difference, but for more advanced input, using scanf can be much more concise than messing around with stream manipulators):

string things = "10 11 12 -10";
int i1, i2, i3, i4, i5, i6;
sscanf(things.c_str(), "%d %d %d %d", &i1, &i2, &i3, &i4);

The reason your example just gives 0's after that is because the stringstream buffer is empty once you extract the -10: you'll have to insert more into the buffer before you can extract more. You can use the same stringstream instance multiple times, but you'll either need to fully use the buffer each time, or realize that there's more in the buffer before the next item you insert into the buffer:

string things = "10 11 12 -10", temp;
int i1, i2, i3, i4;
stringstream into;
into << things; //buffer is now "10 11 12 -10"
into >> i1; //buffer is now " 11 12 -10"
into >> i2; //" 12 -10"
into >> i3; //" -10"
into >> i4; //""

//more code here...

//come back and use the instance again
into << "more: 1 2 3"; //"more: 1 2 3"
into >> temp; //temp is "more:"; into's buffer is " 1 2 3"
into >> i1; //buffer is " 2 3"

//more code here...

//reuse into once again
into << "4 5 6"; // buffer is now " 2 3 4 5 6"
into >> i1; //i1 gets the 2 from before, not the 4 just inserted; buffer now " 3 4 5 6"
into >> i2; //i2==3; buffer is " 4 5 6"

Also, ios (from which stringstream inherits) also defines the ! operator and a cast to void* so that you can conveniently check if extraction failed (technically checks if failbit or badbit is set, and I believe failbit is the one that gets set along with eofbit when there's not enough in the buffer):

string things = "10 11 12 -10";
int i1, i2, i3, i4;
stringstream into;
into << things;
into >> i1 >> i2 >> i3 >> i4;
if (into >> i5) {
    cout << "extraction to i5 succeeded" << endl;
}
if (!(into >> i6)) {
    cout << "extraction to i6 failed" << endl;
}

3 Comments

There is a big difference in using stringstream and sscanf. The former consumes the data from the stream while outputing, but the later doesn't. You can write repeatedly sscanf(things.c_str(), "%d %d %d %d", &i1, &i2, &i3, &i4);
Thank you for your knowledge and it helped. And I have another question is it possible to clear the stringstream buffer?
You can reset the stringstream as well, by seeking to offset zero. Using sscanf is a last resort, and for gurus only. Changing the type of i3, for example, breaks the code horribly for sscanf, while the stringstream will just select another overload for operator>>.
0

Yes it will work.
The only difference I would make is:

string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;

stringstream into(things);    // Initialize in the constructor
into >> i1 >> i2 >> i3 >> i4; // Chain the inputs.

Note the linestream is just like a normal stream and it will run out of items and set failure state when you read past its end.

stringstream into(things)
int val;
while(into >> val)                   // loop exits after 4 numbers as into.eof() 
{                                    // returns true after trying to read the 5 number.
    std::cout << "G(" << val << ")\n";
}

For example I like to do the following when reading multiple lines with 4 numbers:

std::string  line;
while(std::getline(std::cin, line))
{
    /*
     * This way if a line is formatted incorrectly (only 3 numbers)
     * The error is local to the line and we will pick it up in linestream
     * without affecting the scanning of subsequent lines
     */
    std::stringstream linestream(line);

    int i1,i2,i3,i4;
    linestream >> i1 >> i2 >> i3 >> i4;
}

Comments

0

As for your second question Can the same stringstream variable be used multiple times?,
probably clear and seek of stream are needed before reuse.
For example, the following code will serve your second question:

int main() {
  string  s = "-1 2";
  stringstream  ss;
  ss << s;
  int i, j;
  ss >> i >> j;
  cout<< i <<' '<< j <<endl;
  ss.clear();
  ss.seekg( 0 );
  i = j = 0;
  ss >> i >> j;
  cout<< i <<' '<< j <<endl;
}

Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.