7

I'm using a std::stringstream to parse a fixed format string into values. However the last value to be parsed is not fixed length.

To parse such a string I might do:

std::stringstream ss("123ABCDEF1And then the rest of the string");
ss >> std::setw(3) >> nId
   >> std::setw(6) >> sLabel
   >> std::setw(1) >> bFlag
   >> sLeftovers;

But how do I set the width such that the remainder of the string is output?

Through trial and error I found that doing this works:

   >> std::setw(-1) >> sLeftovers;

But what's the correct approach?

Cœur
  • 37,241
  • 25
  • 195
  • 267
DaBozUK
  • 590
  • 1
  • 8
  • 24
  • possible duplicate of ["Roll-Back" or Undo Any Manipulators Applied To A Stream Without Knowing What The Manipulators Were](http://stackoverflow.com/questions/4217704/roll-back-or-undo-any-manipulators-applied-to-a-stream-without-knowing-what-th) – Martin York Nov 21 '12 at 15:32
  • "by doing this works: `std::setw(-1)`" do you mean that `sLeftovers` contains the value 'And' or 'And then the rest of the string'? I find the 'std::setw(-1)` retrieves just the word "And", i.e. the same result as '>> sLeftovers' - it has no affect which is consistent with the documentation for `std::setw` which states that `std::setw` sets the number of characters to be used as the field for the next insertion operation. – mark Nov 21 '12 at 15:41
  • You're quite right Mark, in my actual code there was no space in the data. – DaBozUK Nov 21 '12 at 15:52

4 Answers4

3

Remember that the input operator >> stops reading at whitespace.

Use e.g. std::getline to get the remainder of the string:

std::stringstream ss("123ABCDEF1And then the rest of the string");
ss >> std::setw(3) >> nId
   >> std::setw(6) >> sLabel
   >> std::setw(1) >> bFlag;
std::getline(ss, sLeftovers);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

std::setw only affects exactly one operation, i.e. >> bFlag will reset it to default, so you don't need to do anything to reset it.

i.e. your code should just work

std::stringstream ss("123ABCDEF1And then the rest of the string");
ss >> std::setw(3) >> nId
   >> std::setw(6) >> sLabel
   >> std::setw(1) >> bFlag
   >> sLeftovers;
  • It doesn't, sLeftovers in my code is 1 char "A" (of the "And..."). Are you sure std::setw "only affects exactly one operation"? – DaBozUK Nov 21 '12 at 15:50
1

Try this:

std::stringstream ss("123ABCDEF1And then the rest of the string");
std::stringstream::streamsize initial = ss.width(); // backup
ss >> std::setw(3) >> nId
   >> std::setw(6) >> sLabel
   >> std::setw(1) >> bFlag
   >> sLeftovers;

ss.width(initial); // restore
utnapistim
  • 26,809
  • 3
  • 46
  • 82
0

I'm surprised that setw(-1) actually works for you because I haven't seen this documented, and when I tried your code on VC10, I only got "And" for sLeftovers. I'd probably use std::getline( ss, sLeftovers ) for the remainder of the string, which worked for me in VC10.

Ron Kluth
  • 51
  • 3